@kubun/mcp 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.
package/LICENSE.md ADDED
@@ -0,0 +1,57 @@
1
+ # The Prosperity Public License 3.0.0
2
+
3
+ Contributor: Paul Le Cam
4
+
5
+ Source Code: https://github.com/PaulLeCam/kubun
6
+
7
+ ## Purpose
8
+
9
+ This license allows you to use and share this software for noncommercial purposes for free and to try this software for commercial purposes for thirty days.
10
+
11
+ ## Agreement
12
+
13
+ In order to receive this license, you have to agree to its rules. Those rules are both obligations under that agreement and conditions to your license. Don't do anything with this software that triggers a rule you can't or won't follow.
14
+
15
+ ## Notices
16
+
17
+ Make sure everyone who gets a copy of any part of this software from you, with or without changes, also gets the text of this license and the contributor and source code lines above.
18
+
19
+ ## Commercial Trial
20
+
21
+ Limit your use of this software for commercial purposes to a thirty-day trial period. If you use this software for work, your company gets one trial period for all personnel, not one trial per person.
22
+
23
+ ## Contributions Back
24
+
25
+ Developing feedback, changes, or additions that you contribute back to the contributor on the terms of a standardized public software license such as [the Blue Oak Model License 1.0.0](https://blueoakcouncil.org/license/1.0.0), [the Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0.html), [the MIT license](https://spdx.org/licenses/MIT.html), or [the two-clause BSD license](https://spdx.org/licenses/BSD-2-Clause.html) doesn't count as use for a commercial purpose.
26
+
27
+ ## Personal Uses
28
+
29
+ Personal use for research, experiment, and testing for the benefit of public knowledge, personal study, private entertainment, hobby projects, amateur pursuits, or religious observance, without any anticipated commercial application, doesn't count as use for a commercial purpose.
30
+
31
+ ## Noncommercial Organizations
32
+
33
+ Use by any charitable organization, educational institution, public research organization, public safety or health organization, environmental protection organization, or government institution doesn't count as use for a commercial purpose regardless of the source of funding or obligations resulting from the funding.
34
+
35
+ ## Defense
36
+
37
+ Don't make any legal claim against anyone accusing this software, with or without changes, alone or with other technology, of infringing any patent.
38
+
39
+ ## Copyright
40
+
41
+ The contributor licenses you to do everything with this software that would otherwise infringe their copyright in it.
42
+
43
+ ## Patent
44
+
45
+ The contributor licenses you to do everything with this software that would otherwise infringe any patents they can license or become able to license.
46
+
47
+ ## Reliability
48
+
49
+ The contributor can't revoke this license.
50
+
51
+ ## Excuse
52
+
53
+ You're excused for unknowingly breaking [Notices](#notices) if you take all practical steps to comply within thirty days of learning you broke the rule.
54
+
55
+ ## No Liability
56
+
57
+ ***As far as the law allows, this software comes as is, without any warranty or condition, and the contributor won't be liable to anyone for any damages related to this software or this license, under any kind of legal claim.***
@@ -0,0 +1,20 @@
1
+ import { type TokenSigner } from '@enkaku/token';
2
+ import type { KubunClient } from '@kubun/client';
3
+ export type ClientConfig = {
4
+ type: 'memory';
5
+ } | {
6
+ type: 'sqlite';
7
+ path: string;
8
+ } | {
9
+ type: 'postgres';
10
+ url: string;
11
+ } | {
12
+ type: 'http';
13
+ url: string;
14
+ serverID?: string;
15
+ };
16
+ export type ClientParams = ClientConfig & {
17
+ signer?: TokenSigner;
18
+ };
19
+ export declare function createClient(params: ClientParams): KubunClient;
20
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,WAAW,EAAE,MAAM,eAAe,CAAA;AACnE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAOhD,MAAM,MAAM,YAAY,GACpB;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,GAClB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAChC;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GACjC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AACpD,MAAM,MAAM,YAAY,GAAG,YAAY,GAAG;IAAE,MAAM,CAAC,EAAE,WAAW,CAAA;CAAE,CAAA;AAElE,wBAAgB,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,WAAW,CAkB9D"}
package/lib/client.js ADDED
@@ -0,0 +1,31 @@
1
+ import { randomTokenSigner } from '@enkaku/token';
2
+ import { KubunDB } from '@kubun/db';
3
+ import { PostgresAdapter } from '@kubun/db-postgres';
4
+ import { SQLiteAdapter } from '@kubun/db-sqlite';
5
+ import { HTTPClient } from '@kubun/http-client';
6
+ import { KubunServer } from '@kubun/server';
7
+ export function createClient(params) {
8
+ const signer = params.signer ?? randomTokenSigner();
9
+ if (params.type === 'http') {
10
+ return new HTTPClient({
11
+ url: params.url,
12
+ signer,
13
+ serverID: params.serverID
14
+ });
15
+ }
16
+ const adapter = params.type === 'postgres' ? new PostgresAdapter({
17
+ url: params.url
18
+ }) : new SQLiteAdapter({
19
+ database: params.type === 'sqlite' ? params.path : ':memory:'
20
+ });
21
+ const db = new KubunDB({
22
+ adapter
23
+ });
24
+ const server = new KubunServer({
25
+ db,
26
+ id: signer.id
27
+ });
28
+ return server.createClient({
29
+ signer
30
+ });
31
+ }
@@ -0,0 +1,9 @@
1
+ import type { TokenSigner } from '@enkaku/token';
2
+ import type { ServerConfig } from '@mokei/context-server';
3
+ export type MCPConfig = {
4
+ connect?: string;
5
+ database?: string;
6
+ signer?: TokenSigner;
7
+ };
8
+ export declare function createConfig(config?: MCPConfig): ServerConfig;
9
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAChD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAA;AAOzD,MAAM,MAAM,SAAS,GAAG;IACtB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,MAAM,CAAC,EAAE,WAAW,CAAA;CACrB,CAAA;AAeD,wBAAgB,YAAY,CAAC,MAAM,GAAE,SAAc,GAAG,YAAY,CAcjE"}
package/lib/config.js ADDED
@@ -0,0 +1,45 @@
1
+ import { createClient } from './client.js';
2
+ import { prompts } from './prompts/index.js';
3
+ import { createClusterTools } from './tools/cluster.js';
4
+ import { createGraphTools } from './tools/graph.js';
5
+ function parseConfig(config) {
6
+ if (config.connect != null) {
7
+ return {
8
+ type: 'http',
9
+ url: config.connect,
10
+ signer: config.signer
11
+ };
12
+ }
13
+ if (config.database != null) {
14
+ if (config.database.startsWith('postgres://')) {
15
+ return {
16
+ type: 'postgres',
17
+ url: config.database,
18
+ signer: config.signer
19
+ };
20
+ }
21
+ return {
22
+ type: 'sqlite',
23
+ path: config.database,
24
+ signer: config.signer
25
+ };
26
+ }
27
+ return {
28
+ type: 'memory',
29
+ signer: config.signer
30
+ };
31
+ }
32
+ export function createConfig(config = {}) {
33
+ const client = createClient(parseConfig(config));
34
+ const clusterTools = createClusterTools(client);
35
+ const graphTools = createGraphTools(client);
36
+ return {
37
+ name: 'kubun',
38
+ version: '0.1.0',
39
+ prompts,
40
+ tools: {
41
+ ...clusterTools,
42
+ ...graphTools
43
+ }
44
+ };
45
+ }
package/lib/index.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ export { type ClientParams, createClient } from './client.js';
2
+ export { createConfig, type MCPConfig } from './config.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC7D,OAAO,EAAE,YAAY,EAAE,KAAK,SAAS,EAAE,MAAM,aAAa,CAAA"}
package/lib/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export { createClient } from './client.js';
2
+ export { createConfig } from './config.js';
@@ -0,0 +1,2 @@
1
+ export declare const KUBUN_PROMPT_INSTRUCTIONS = "# Kubun Protocol Data Model Generator\n\nYou are an expert at creating data models following the Kubun protocol specification. Your task is to generate valid JSON schemas for data models based on user requirements.\n\n## Core Principles\n\n**Automatic Server Fields (DO NOT INCLUDE):**\n- `id` - Server generates globally unique DocID automatically\n- `createdAt` - Server generates timestamp automatically\n- `updatedAt` - Server generates timestamp automatically\n- Owner relations - Server handles user/owner associations automatically\n\n**Model Behaviors:**\n- `default` - Standard concrete models for real entities\n- `interface` - Abstract contracts that other models implement\n- `unique` - Models with uniqueness constraints on specific fields\n\n---\n\n## Built-in Interfaces\n\n### Node (Implicit Base Interface)\n\n**All models implicitly implement the `Node` interface.** This is the base interface for all documents in the system.\n\n- **DO NOT** create a `Node` interface model\n- **DO NOT** include `\"Node\"` in any model's `interfaces` array\n- **DO** use `null` as a `relationModel` value when a field can reference any document\n\n**Example - Field that can link to any document:**\n```json\n{\n \"fieldsMeta\": {\n \"linkedItemId\": {\n \"relationModel\": null\n }\n }\n}\n```\n\n---\n\n## Schema Structure\n\nEach model must include:\n```json\n{\n \"name\": \"PascalCaseModelName\",\n \"version\": \"1.0\",\n \"interfaces\": [],\n \"schema\": { /* JSON Schema definition */ },\n \"fieldsMeta\": { /* DocID field metadata */ },\n \"behavior\": \"default|interface|unique\",\n \"uniqueFields\": [\"field1\", \"field2\"]\n}\n```\n\n| Field | Required | Description |\n|-------|----------|-------------|\n| `name` | Yes | PascalCase model name |\n| `version` | Yes | Schema version (use `\"1.0\"`) |\n| `interfaces` | Yes | Array of interface references (see Interface References) |\n| `schema` | Yes | JSON Schema definition |\n| `fieldsMeta` | Yes | DocID field relationship metadata (can be empty `{}`) |\n| `behavior` | Yes | One of: `default`, `interface`, `unique` |\n| `uniqueFields` | Only for `unique` behavior | Array of field names that must be unique |\n\n---\n\n## Interface References\n\nThe `interfaces` array specifies which interfaces a model implements. Reference format depends on where the interface is defined:\n\n| Interface Location | Reference Format | Example |\n|--------------------|------------------|---------|\n| Existing in database | Model ID | `\"k1a2b3c4d5e6f7g8h9\"` |\n| In same cluster being generated | Array index | `\"#0\"` |\n\n**Rules:**\n- All models implicitly implement `Node` - never include it in the interfaces array\n- When generating a new cluster, define interface models FIRST (at lower indices) so concrete models can reference them\n- Use `#N` format where N is the zero-based array index of the interface model in the cluster\n\n**Example - Model implementing cluster interfaces:**\n```json\n{\n \"name\": \"Task\",\n \"interfaces\": [\"#0\", \"#2\"],\n ...\n}\n```\n\n---\n\n## Relations Between Models\n\nUse `fieldsMeta` to define DocID relationships:\n\n| Target Location | Reference Format | Description |\n|-----------------|------------------|-------------|\n| Any document (polymorphic to Node) | `null` | Field can link to any item in the system |\n| Existing in database | Model ID | `\"k1a2b3c4d5e6f7g8h9\"` |\n| In same cluster being generated | Array index | `\"#2\"` |\n\n**Example:**\n```json\n{\n \"fieldsMeta\": {\n \"taskListId\": {\n \"relationModel\": \"#5\"\n },\n \"categoryId\": {\n \"relationModel\": \"k1a2b3c4d5e6f7g8h9\"\n },\n \"linkedItemId\": {\n \"relationModel\": null\n }\n }\n}\n```\n\n---\n\n## Naming Conventions\n\n| Element | Convention | Example |\n|---------|------------|---------|\n| Model names | PascalCase starting with uppercase | `UserProfile`, `BlogPost` |\n| Field names | camelCase starting with lowercase | `firstName`, `createdDate` |\n| Type titles | PascalCase | `EmailAddress`, `PhoneNumber` |\n| Enum values | UPPERCASE_UNDERSCORE | `ACTIVE`, `PENDING_APPROVAL` |\n\n---\n\n## Available Data Types\n\n### Predefined Types (Use When Applicable)\n\nWhen a predefined type matches your use case, copy its exact definition into the `definitions` section and reference it. Never create custom types that duplicate predefined functionality.\n\n| Type | Purpose |\n|------|---------|\n| `AttachmentID` | File/media references |\n| `BigInt` | Large integers |\n| `DateTime` | ISO 8601 date-time |\n| `DID` | Decentralized identifiers |\n| `DocID` | Document references |\n| `Duration` | ISO 8601 duration |\n| `JSONObject` | Flexible JSON data |\n| `Latitude` / `Longitude` | Geographic coordinates |\n| `LocalDate` | Date without time (YYYY-MM-DD) |\n| `LocalDateTime` | Local date-time |\n| `LocalTime` | Time without date |\n| `Locale` | Language/region codes |\n| `TimeZone` | Timezone identifiers |\n| `URL` | Web addresses |\n| `UtcOffset` | UTC time offsets |\n\n**Usage Pattern:**\n```json\n{\n \"properties\": {\n \"scheduledAt\": { \"$ref\": \"#/definitions/DateTime\" }\n },\n \"definitions\": {\n \"DateTime\": { \"type\": \"string\", \"format\": \"date-time\", \"title\": \"DateTime\" }\n }\n}\n```\n\n### Primitive Types\n\n| Type | Variants |\n|------|----------|\n| `boolean` | True/false values |\n| `integer` | Whole numbers (with optional min/max) |\n| `number` | Decimal numbers (with optional min/max) |\n| `string` | Plain text, `const`, `pattern`, `enum`, `format` |\n\n### Complex Types\n\n| Type | Description |\n|------|-------------|\n| `array` | Collections of items |\n| `object` | Structured data with properties |\n\n---\n\n## Example Patterns\n\n### Interface Model\n```json\n{\n \"name\": \"Completable\",\n \"version\": \"1.0\",\n \"interfaces\": [],\n \"behavior\": \"interface\",\n \"schema\": {\n \"type\": \"object\",\n \"properties\": {\n \"completed\": { \"$ref\": \"#/definitions/Completed\" },\n \"completedAt\": { \"$ref\": \"#/definitions/DateTime\" }\n },\n \"required\": [\"completed\"],\n \"additionalProperties\": true,\n \"definitions\": {\n \"Completed\": { \"type\": \"boolean\", \"title\": \"Completed\", \"default\": false },\n \"DateTime\": { \"type\": \"string\", \"format\": \"date-time\", \"title\": \"DateTime\" }\n }\n },\n \"fieldsMeta\": {}\n}\n```\n\n**Note:** Interface schemas use `\"additionalProperties\": true` to allow implementing models to add fields.\n\n### Concrete Model (Implementing Interfaces)\n```json\n{\n \"name\": \"Task\",\n \"version\": \"1.0\",\n \"interfaces\": [\"#0\", \"#1\"],\n \"behavior\": \"default\",\n \"schema\": {\n \"type\": \"object\",\n \"properties\": {\n \"title\": { \"$ref\": \"#/definitions/Title\" },\n \"description\": { \"$ref\": \"#/definitions/Description\" },\n \"completed\": { \"$ref\": \"#/definitions/Completed\" },\n \"completedAt\": { \"$ref\": \"#/definitions/DateTime\" },\n \"priority\": { \"$ref\": \"#/definitions/Priority\" },\n \"taskListId\": { \"$ref\": \"#/definitions/DocID\" }\n },\n \"required\": [\"title\", \"completed\", \"priority\"],\n \"additionalProperties\": false,\n \"definitions\": {\n \"Title\": { \"type\": \"string\", \"title\": \"Title\", \"minLength\": 1, \"maxLength\": 200 },\n \"Description\": { \"type\": \"string\", \"title\": \"Description\", \"maxLength\": 5000 },\n \"Completed\": { \"type\": \"boolean\", \"title\": \"Completed\", \"default\": false },\n \"DateTime\": { \"type\": \"string\", \"format\": \"date-time\", \"title\": \"DateTime\" },\n \"Priority\": {\n \"type\": \"string\",\n \"title\": \"Priority\",\n \"enum\": [\"LOW\", \"MEDIUM\", \"HIGH\", \"URGENT\"],\n \"default\": \"MEDIUM\"\n },\n \"DocID\": { \"type\": \"string\", \"title\": \"DocID\", \"pattern\": \"^k[0-9a-z]{10,120}$\" }\n }\n },\n \"fieldsMeta\": {\n \"taskListId\": { \"relationModel\": \"#5\" }\n }\n}\n```\n\n**Note:** Concrete schemas use `\"additionalProperties\": false` to enforce strict structure.\n\n### Unique Constraint Model\n```json\n{\n \"name\": \"UserProfile\",\n \"version\": \"1.0\",\n \"interfaces\": [],\n \"behavior\": \"unique\",\n \"uniqueFields\": [\"email\"],\n \"schema\": {\n \"type\": \"object\",\n \"properties\": {\n \"email\": { \"$ref\": \"#/definitions/Email\" },\n \"displayName\": { \"$ref\": \"#/definitions/DisplayName\" }\n },\n \"required\": [\"email\"],\n \"additionalProperties\": false,\n \"definitions\": {\n \"Email\": { \"type\": \"string\", \"format\": \"email\", \"title\": \"Email\" },\n \"DisplayName\": { \"type\": \"string\", \"title\": \"DisplayName\", \"maxLength\": 100 }\n }\n },\n \"fieldsMeta\": {}\n}\n```\n\n### Model with Any-Document Reference\n```json\n{\n \"name\": \"Reminder\",\n \"version\": \"1.0\",\n \"interfaces\": [\"#0\"],\n \"behavior\": \"default\",\n \"schema\": {\n \"type\": \"object\",\n \"properties\": {\n \"title\": { \"$ref\": \"#/definitions/Title\" },\n \"linkedItemId\": { \"$ref\": \"#/definitions/DocID\" },\n \"remindAt\": { \"$ref\": \"#/definitions/DateTime\" }\n },\n \"required\": [\"title\", \"remindAt\"],\n \"additionalProperties\": false,\n \"definitions\": {\n \"Title\": { \"type\": \"string\", \"title\": \"Title\", \"minLength\": 1, \"maxLength\": 200 },\n \"DocID\": { \"type\": \"string\", \"title\": \"DocID\", \"pattern\": \"^k[0-9a-z]{10,120}$\" },\n \"DateTime\": { \"type\": \"string\", \"format\": \"date-time\", \"title\": \"DateTime\" }\n }\n },\n \"fieldsMeta\": {\n \"linkedItemId\": { \"relationModel\": null }\n }\n}\n```\n\n---\n\n## Generation Guidelines\n\n1. **Never create a Node interface** - it's built-in and implicit\n2. **Never include \"Node\" in interfaces array** - all models inherit it automatically\n3. **Use `null` for any-document relations** - this represents the Node interface\n4. **Define interfaces first in clusters** - place them at lower indices (0, 1, 2...) so concrete models can reference them with `#N`\n5. **Ask clarifying questions** about requirements if needed\n6. **Choose appropriate behavior** (`default` / `interface` / `unique`)\n7. **Use predefined types** when they match the use case\n8. **Define clear field relationships** using `fieldsMeta`\n9. **Include reasonable validation** (lengths, patterns, ranges)\n10. **Follow naming conventions** strictly\n11. **Make required fields explicit**\n12. **Concrete models must include all interface fields** - copy the field definitions from implemented interfaces\n\n---\n\n## Cluster Organization\n\nWhen generating a model cluster, organize models in this order:\n\n1. **Interface models** (indices 0, 1, 2, ...) - Define abstract contracts first\n2. **Shared/referenced models** (e.g., Tag) - Models referenced by many others\n3. **Domain models** - Concrete models grouped by domain\n\n**Example cluster structure:**\n```\n#0 Schedulable (interface)\n#1 Completable (interface)\n#2 Prioritizable (interface)\n#3 Taggable (interface)\n#4 Tag (referenced by Taggable)\n#5 Event (implements #0, #3)\n#6 Task (implements #1, #2, #3)\n#7 Project (implements #1)\n```\n\n---\n\n## Response Format\n\nAlways generate models as a JSON array, even when a single model is needed. Validate that your output follows the specification exactly.";
2
+ //# sourceMappingURL=data-model-designer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"data-model-designer.d.ts","sourceRoot":"","sources":["../../src/prompts/data-model-designer.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,yBAAyB,oyWAiWmG,CAAA"}
@@ -0,0 +1,354 @@
1
+ export const KUBUN_PROMPT_INSTRUCTIONS = `# Kubun Protocol Data Model Generator
2
+
3
+ You are an expert at creating data models following the Kubun protocol specification. Your task is to generate valid JSON schemas for data models based on user requirements.
4
+
5
+ ## Core Principles
6
+
7
+ **Automatic Server Fields (DO NOT INCLUDE):**
8
+ - \`id\` - Server generates globally unique DocID automatically
9
+ - \`createdAt\` - Server generates timestamp automatically
10
+ - \`updatedAt\` - Server generates timestamp automatically
11
+ - Owner relations - Server handles user/owner associations automatically
12
+
13
+ **Model Behaviors:**
14
+ - \`default\` - Standard concrete models for real entities
15
+ - \`interface\` - Abstract contracts that other models implement
16
+ - \`unique\` - Models with uniqueness constraints on specific fields
17
+
18
+ ---
19
+
20
+ ## Built-in Interfaces
21
+
22
+ ### Node (Implicit Base Interface)
23
+
24
+ **All models implicitly implement the \`Node\` interface.** This is the base interface for all documents in the system.
25
+
26
+ - **DO NOT** create a \`Node\` interface model
27
+ - **DO NOT** include \`"Node"\` in any model's \`interfaces\` array
28
+ - **DO** use \`null\` as a \`relationModel\` value when a field can reference any document
29
+
30
+ **Example - Field that can link to any document:**
31
+ \`\`\`json
32
+ {
33
+ "fieldsMeta": {
34
+ "linkedItemId": {
35
+ "relationModel": null
36
+ }
37
+ }
38
+ }
39
+ \`\`\`
40
+
41
+ ---
42
+
43
+ ## Schema Structure
44
+
45
+ Each model must include:
46
+ \`\`\`json
47
+ {
48
+ "name": "PascalCaseModelName",
49
+ "version": "1.0",
50
+ "interfaces": [],
51
+ "schema": { /* JSON Schema definition */ },
52
+ "fieldsMeta": { /* DocID field metadata */ },
53
+ "behavior": "default|interface|unique",
54
+ "uniqueFields": ["field1", "field2"]
55
+ }
56
+ \`\`\`
57
+
58
+ | Field | Required | Description |
59
+ |-------|----------|-------------|
60
+ | \`name\` | Yes | PascalCase model name |
61
+ | \`version\` | Yes | Schema version (use \`"1.0"\`) |
62
+ | \`interfaces\` | Yes | Array of interface references (see Interface References) |
63
+ | \`schema\` | Yes | JSON Schema definition |
64
+ | \`fieldsMeta\` | Yes | DocID field relationship metadata (can be empty \`{}\`) |
65
+ | \`behavior\` | Yes | One of: \`default\`, \`interface\`, \`unique\` |
66
+ | \`uniqueFields\` | Only for \`unique\` behavior | Array of field names that must be unique |
67
+
68
+ ---
69
+
70
+ ## Interface References
71
+
72
+ The \`interfaces\` array specifies which interfaces a model implements. Reference format depends on where the interface is defined:
73
+
74
+ | Interface Location | Reference Format | Example |
75
+ |--------------------|------------------|---------|
76
+ | Existing in database | Model ID | \`"k1a2b3c4d5e6f7g8h9"\` |
77
+ | In same cluster being generated | Array index | \`"#0"\` |
78
+
79
+ **Rules:**
80
+ - All models implicitly implement \`Node\` - never include it in the interfaces array
81
+ - When generating a new cluster, define interface models FIRST (at lower indices) so concrete models can reference them
82
+ - Use \`#N\` format where N is the zero-based array index of the interface model in the cluster
83
+
84
+ **Example - Model implementing cluster interfaces:**
85
+ \`\`\`json
86
+ {
87
+ "name": "Task",
88
+ "interfaces": ["#0", "#2"],
89
+ ...
90
+ }
91
+ \`\`\`
92
+
93
+ ---
94
+
95
+ ## Relations Between Models
96
+
97
+ Use \`fieldsMeta\` to define DocID relationships:
98
+
99
+ | Target Location | Reference Format | Description |
100
+ |-----------------|------------------|-------------|
101
+ | Any document (polymorphic to Node) | \`null\` | Field can link to any item in the system |
102
+ | Existing in database | Model ID | \`"k1a2b3c4d5e6f7g8h9"\` |
103
+ | In same cluster being generated | Array index | \`"#2"\` |
104
+
105
+ **Example:**
106
+ \`\`\`json
107
+ {
108
+ "fieldsMeta": {
109
+ "taskListId": {
110
+ "relationModel": "#5"
111
+ },
112
+ "categoryId": {
113
+ "relationModel": "k1a2b3c4d5e6f7g8h9"
114
+ },
115
+ "linkedItemId": {
116
+ "relationModel": null
117
+ }
118
+ }
119
+ }
120
+ \`\`\`
121
+
122
+ ---
123
+
124
+ ## Naming Conventions
125
+
126
+ | Element | Convention | Example |
127
+ |---------|------------|---------|
128
+ | Model names | PascalCase starting with uppercase | \`UserProfile\`, \`BlogPost\` |
129
+ | Field names | camelCase starting with lowercase | \`firstName\`, \`createdDate\` |
130
+ | Type titles | PascalCase | \`EmailAddress\`, \`PhoneNumber\` |
131
+ | Enum values | UPPERCASE_UNDERSCORE | \`ACTIVE\`, \`PENDING_APPROVAL\` |
132
+
133
+ ---
134
+
135
+ ## Available Data Types
136
+
137
+ ### Predefined Types (Use When Applicable)
138
+
139
+ When a predefined type matches your use case, copy its exact definition into the \`definitions\` section and reference it. Never create custom types that duplicate predefined functionality.
140
+
141
+ | Type | Purpose |
142
+ |------|---------|
143
+ | \`AttachmentID\` | File/media references |
144
+ | \`BigInt\` | Large integers |
145
+ | \`DateTime\` | ISO 8601 date-time |
146
+ | \`DID\` | Decentralized identifiers |
147
+ | \`DocID\` | Document references |
148
+ | \`Duration\` | ISO 8601 duration |
149
+ | \`JSONObject\` | Flexible JSON data |
150
+ | \`Latitude\` / \`Longitude\` | Geographic coordinates |
151
+ | \`LocalDate\` | Date without time (YYYY-MM-DD) |
152
+ | \`LocalDateTime\` | Local date-time |
153
+ | \`LocalTime\` | Time without date |
154
+ | \`Locale\` | Language/region codes |
155
+ | \`TimeZone\` | Timezone identifiers |
156
+ | \`URL\` | Web addresses |
157
+ | \`UtcOffset\` | UTC time offsets |
158
+
159
+ **Usage Pattern:**
160
+ \`\`\`json
161
+ {
162
+ "properties": {
163
+ "scheduledAt": { "$ref": "#/definitions/DateTime" }
164
+ },
165
+ "definitions": {
166
+ "DateTime": { "type": "string", "format": "date-time", "title": "DateTime" }
167
+ }
168
+ }
169
+ \`\`\`
170
+
171
+ ### Primitive Types
172
+
173
+ | Type | Variants |
174
+ |------|----------|
175
+ | \`boolean\` | True/false values |
176
+ | \`integer\` | Whole numbers (with optional min/max) |
177
+ | \`number\` | Decimal numbers (with optional min/max) |
178
+ | \`string\` | Plain text, \`const\`, \`pattern\`, \`enum\`, \`format\` |
179
+
180
+ ### Complex Types
181
+
182
+ | Type | Description |
183
+ |------|-------------|
184
+ | \`array\` | Collections of items |
185
+ | \`object\` | Structured data with properties |
186
+
187
+ ---
188
+
189
+ ## Example Patterns
190
+
191
+ ### Interface Model
192
+ \`\`\`json
193
+ {
194
+ "name": "Completable",
195
+ "version": "1.0",
196
+ "interfaces": [],
197
+ "behavior": "interface",
198
+ "schema": {
199
+ "type": "object",
200
+ "properties": {
201
+ "completed": { "$ref": "#/definitions/Completed" },
202
+ "completedAt": { "$ref": "#/definitions/DateTime" }
203
+ },
204
+ "required": ["completed"],
205
+ "additionalProperties": true,
206
+ "definitions": {
207
+ "Completed": { "type": "boolean", "title": "Completed", "default": false },
208
+ "DateTime": { "type": "string", "format": "date-time", "title": "DateTime" }
209
+ }
210
+ },
211
+ "fieldsMeta": {}
212
+ }
213
+ \`\`\`
214
+
215
+ **Note:** Interface schemas use \`"additionalProperties": true\` to allow implementing models to add fields.
216
+
217
+ ### Concrete Model (Implementing Interfaces)
218
+ \`\`\`json
219
+ {
220
+ "name": "Task",
221
+ "version": "1.0",
222
+ "interfaces": ["#0", "#1"],
223
+ "behavior": "default",
224
+ "schema": {
225
+ "type": "object",
226
+ "properties": {
227
+ "title": { "$ref": "#/definitions/Title" },
228
+ "description": { "$ref": "#/definitions/Description" },
229
+ "completed": { "$ref": "#/definitions/Completed" },
230
+ "completedAt": { "$ref": "#/definitions/DateTime" },
231
+ "priority": { "$ref": "#/definitions/Priority" },
232
+ "taskListId": { "$ref": "#/definitions/DocID" }
233
+ },
234
+ "required": ["title", "completed", "priority"],
235
+ "additionalProperties": false,
236
+ "definitions": {
237
+ "Title": { "type": "string", "title": "Title", "minLength": 1, "maxLength": 200 },
238
+ "Description": { "type": "string", "title": "Description", "maxLength": 5000 },
239
+ "Completed": { "type": "boolean", "title": "Completed", "default": false },
240
+ "DateTime": { "type": "string", "format": "date-time", "title": "DateTime" },
241
+ "Priority": {
242
+ "type": "string",
243
+ "title": "Priority",
244
+ "enum": ["LOW", "MEDIUM", "HIGH", "URGENT"],
245
+ "default": "MEDIUM"
246
+ },
247
+ "DocID": { "type": "string", "title": "DocID", "pattern": "^k[0-9a-z]{10,120}$" }
248
+ }
249
+ },
250
+ "fieldsMeta": {
251
+ "taskListId": { "relationModel": "#5" }
252
+ }
253
+ }
254
+ \`\`\`
255
+
256
+ **Note:** Concrete schemas use \`"additionalProperties": false\` to enforce strict structure.
257
+
258
+ ### Unique Constraint Model
259
+ \`\`\`json
260
+ {
261
+ "name": "UserProfile",
262
+ "version": "1.0",
263
+ "interfaces": [],
264
+ "behavior": "unique",
265
+ "uniqueFields": ["email"],
266
+ "schema": {
267
+ "type": "object",
268
+ "properties": {
269
+ "email": { "$ref": "#/definitions/Email" },
270
+ "displayName": { "$ref": "#/definitions/DisplayName" }
271
+ },
272
+ "required": ["email"],
273
+ "additionalProperties": false,
274
+ "definitions": {
275
+ "Email": { "type": "string", "format": "email", "title": "Email" },
276
+ "DisplayName": { "type": "string", "title": "DisplayName", "maxLength": 100 }
277
+ }
278
+ },
279
+ "fieldsMeta": {}
280
+ }
281
+ \`\`\`
282
+
283
+ ### Model with Any-Document Reference
284
+ \`\`\`json
285
+ {
286
+ "name": "Reminder",
287
+ "version": "1.0",
288
+ "interfaces": ["#0"],
289
+ "behavior": "default",
290
+ "schema": {
291
+ "type": "object",
292
+ "properties": {
293
+ "title": { "$ref": "#/definitions/Title" },
294
+ "linkedItemId": { "$ref": "#/definitions/DocID" },
295
+ "remindAt": { "$ref": "#/definitions/DateTime" }
296
+ },
297
+ "required": ["title", "remindAt"],
298
+ "additionalProperties": false,
299
+ "definitions": {
300
+ "Title": { "type": "string", "title": "Title", "minLength": 1, "maxLength": 200 },
301
+ "DocID": { "type": "string", "title": "DocID", "pattern": "^k[0-9a-z]{10,120}$" },
302
+ "DateTime": { "type": "string", "format": "date-time", "title": "DateTime" }
303
+ }
304
+ },
305
+ "fieldsMeta": {
306
+ "linkedItemId": { "relationModel": null }
307
+ }
308
+ }
309
+ \`\`\`
310
+
311
+ ---
312
+
313
+ ## Generation Guidelines
314
+
315
+ 1. **Never create a Node interface** - it's built-in and implicit
316
+ 2. **Never include "Node" in interfaces array** - all models inherit it automatically
317
+ 3. **Use \`null\` for any-document relations** - this represents the Node interface
318
+ 4. **Define interfaces first in clusters** - place them at lower indices (0, 1, 2...) so concrete models can reference them with \`#N\`
319
+ 5. **Ask clarifying questions** about requirements if needed
320
+ 6. **Choose appropriate behavior** (\`default\` / \`interface\` / \`unique\`)
321
+ 7. **Use predefined types** when they match the use case
322
+ 8. **Define clear field relationships** using \`fieldsMeta\`
323
+ 9. **Include reasonable validation** (lengths, patterns, ranges)
324
+ 10. **Follow naming conventions** strictly
325
+ 11. **Make required fields explicit**
326
+ 12. **Concrete models must include all interface fields** - copy the field definitions from implemented interfaces
327
+
328
+ ---
329
+
330
+ ## Cluster Organization
331
+
332
+ When generating a model cluster, organize models in this order:
333
+
334
+ 1. **Interface models** (indices 0, 1, 2, ...) - Define abstract contracts first
335
+ 2. **Shared/referenced models** (e.g., Tag) - Models referenced by many others
336
+ 3. **Domain models** - Concrete models grouped by domain
337
+
338
+ **Example cluster structure:**
339
+ \`\`\`
340
+ #0 Schedulable (interface)
341
+ #1 Completable (interface)
342
+ #2 Prioritizable (interface)
343
+ #3 Taggable (interface)
344
+ #4 Tag (referenced by Taggable)
345
+ #5 Event (implements #0, #3)
346
+ #6 Task (implements #1, #2, #3)
347
+ #7 Project (implements #1)
348
+ \`\`\`
349
+
350
+ ---
351
+
352
+ ## Response Format
353
+
354
+ Always generate models as a JSON array, even when a single model is needed. Validate that your output follows the specification exactly.`;
@@ -0,0 +1,15 @@
1
+ export declare const prompts: {
2
+ 'data-model-designer': {
3
+ description: string;
4
+ handler: () => {
5
+ messages: {
6
+ role: "user";
7
+ content: {
8
+ type: "text";
9
+ text: string;
10
+ };
11
+ }[];
12
+ };
13
+ };
14
+ };
15
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/prompts/index.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,OAAO;;;;;;;;;;;;;CAenB,CAAA"}
@@ -0,0 +1,19 @@
1
+ import { KUBUN_PROMPT_INSTRUCTIONS } from './data-model-designer.js';
2
+ export const prompts = {
3
+ 'data-model-designer': {
4
+ description: 'Instructions to help design a data model following the Kubun protocol specification',
5
+ handler: ()=>{
6
+ return {
7
+ messages: [
8
+ {
9
+ role: 'user',
10
+ content: {
11
+ type: 'text',
12
+ text: KUBUN_PROMPT_INSTRUCTIONS
13
+ }
14
+ }
15
+ ]
16
+ };
17
+ }
18
+ }
19
+ };
package/lib/run.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=run.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":""}
package/lib/run.js ADDED
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env node
2
+ import { parseArgs } from 'node:util';
3
+ import { serveProcess } from '@mokei/context-server';
4
+ import { createConfig } from './config.js';
5
+ const args = parseArgs({
6
+ options: {
7
+ connect: {
8
+ type: 'string'
9
+ },
10
+ db: {
11
+ type: 'string'
12
+ }
13
+ }
14
+ });
15
+ const config = createConfig({
16
+ connect: args.values.connect,
17
+ database: args.values.db
18
+ });
19
+ serveProcess(config);
@@ -0,0 +1,6 @@
1
+ import type { KubunClient } from '@kubun/client';
2
+ import { createTool } from '@mokei/context-server';
3
+ type ToolDefinition = ReturnType<typeof createTool>;
4
+ export declare function createClusterTools(client: KubunClient): Record<string, ToolDefinition>;
5
+ export {};
6
+ //# sourceMappingURL=cluster.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cluster.d.ts","sourceRoot":"","sources":["../../src/tools/cluster.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAEhD,OAAO,EAAE,UAAU,EAAe,MAAM,uBAAuB,CAAA;AAE/D,KAAK,cAAc,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAA;AAEnD,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CA8CtF"}
@@ -0,0 +1,71 @@
1
+ import { ClusterBuilder, clusterModel } from '@kubun/protocol';
2
+ import { createTool } from '@mokei/context-server';
3
+ export function createClusterTools(client) {
4
+ const create_cluster = createTool('Create a new cluster from model definitions', {
5
+ type: 'object',
6
+ properties: {
7
+ models: {
8
+ type: 'array',
9
+ items: {
10
+ type: 'object'
11
+ }
12
+ }
13
+ },
14
+ required: [
15
+ 'models'
16
+ ],
17
+ additionalProperties: false
18
+ }, async (ctx)=>{
19
+ const builder = new ClusterBuilder();
20
+ builder.addAll(ctx.arguments.models);
21
+ const cluster = builder.build();
22
+ return {
23
+ content: [
24
+ {
25
+ type: 'text',
26
+ text: 'Cluster created'
27
+ }
28
+ ],
29
+ structuredContent: {
30
+ cluster
31
+ }
32
+ };
33
+ });
34
+ const deploy_clusters = createTool('Deploy clusters to the Kubun backend', {
35
+ type: 'object',
36
+ properties: {
37
+ clusters: {
38
+ type: 'array',
39
+ items: clusterModel
40
+ },
41
+ id: {
42
+ type: 'string'
43
+ }
44
+ },
45
+ required: [
46
+ 'clusters'
47
+ ],
48
+ additionalProperties: false
49
+ }, async (ctx)=>{
50
+ const result = await client.deployGraph({
51
+ id: ctx.arguments.id,
52
+ clusters: ctx.arguments.clusters
53
+ });
54
+ return {
55
+ content: [
56
+ {
57
+ type: 'text',
58
+ text: `Clusters deployed to graph "${result.id}"`
59
+ }
60
+ ],
61
+ structuredContent: {
62
+ id: result.id,
63
+ models: result.models
64
+ }
65
+ };
66
+ });
67
+ return {
68
+ create_cluster,
69
+ deploy_clusters
70
+ };
71
+ }
@@ -0,0 +1,6 @@
1
+ import type { KubunClient } from '@kubun/client';
2
+ import { createTool } from '@mokei/context-server';
3
+ type ToolDefinition = ReturnType<typeof createTool>;
4
+ export declare function createGraphTools(client: KubunClient): Record<string, ToolDefinition>;
5
+ export {};
6
+ //# sourceMappingURL=graph.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graph.d.ts","sourceRoot":"","sources":["../../src/tools/graph.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAKhD,OAAO,EAAE,UAAU,EAAe,MAAM,uBAAuB,CAAA;AAG/D,KAAK,cAAc,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAA;AA2BnD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAuKpF"}
@@ -0,0 +1,248 @@
1
+ import { createSchema } from '@kubun/graphql';
2
+ import { createTool } from '@mokei/context-server';
3
+ import { printSchema } from 'graphql';
4
+ function getModelsInfo(result) {
5
+ if (result.models == null) {
6
+ return {};
7
+ }
8
+ const aliases = result.aliases ?? {};
9
+ return Object.entries(result.models).reduce((acc, [id, model])=>{
10
+ const alias = aliases[id] ?? model.name;
11
+ acc[alias] = {
12
+ id,
13
+ behavior: model.behavior,
14
+ interfaces: model.interfaces,
15
+ fields: Object.keys(model.schema.properties)
16
+ };
17
+ return acc;
18
+ }, {});
19
+ }
20
+ export function createGraphTools(client) {
21
+ const graph_list = createTool('List all available graphs', {}, async ()=>{
22
+ const result = await client.listGraphs();
23
+ const graphs = result.graphs.map((graph)=>`${graph.name} (${graph.id})`).join(', ');
24
+ return {
25
+ content: [
26
+ {
27
+ type: 'text',
28
+ text: graphs === '' ? 'No graphs available' : `Available graphs: ${graphs}`
29
+ }
30
+ ],
31
+ structuredContent: {
32
+ graphs: result.graphs
33
+ }
34
+ };
35
+ });
36
+ const graph_info = createTool('Get information about a specific graph', {
37
+ type: 'object',
38
+ properties: {
39
+ id: {
40
+ type: 'string'
41
+ }
42
+ },
43
+ required: [
44
+ 'id'
45
+ ],
46
+ additionalProperties: false
47
+ }, async (ctx)=>{
48
+ try {
49
+ const result = await client.loadGraph({
50
+ id: ctx.arguments.id
51
+ });
52
+ if (result.models == null) {
53
+ throw new Error(`Models not found for graph: ${ctx.arguments.id}`);
54
+ }
55
+ const info = getModelsInfo(result);
56
+ return {
57
+ content: [
58
+ {
59
+ type: 'text',
60
+ text: JSON.stringify(info)
61
+ }
62
+ ],
63
+ structuredContent: info
64
+ };
65
+ } catch (error) {
66
+ return {
67
+ isError: true,
68
+ content: [
69
+ {
70
+ type: 'text',
71
+ text: `Failed to get GraphQL schema: ${error instanceof Error ? error.message : String(error)}`
72
+ }
73
+ ]
74
+ };
75
+ }
76
+ });
77
+ const graph_schema = createTool('Get the GraphQL schema for the given graph ID', {
78
+ type: 'object',
79
+ properties: {
80
+ id: {
81
+ type: 'string'
82
+ }
83
+ },
84
+ required: [
85
+ 'id'
86
+ ],
87
+ additionalProperties: false
88
+ }, async (ctx)=>{
89
+ try {
90
+ const result = await client.loadGraph({
91
+ id: ctx.arguments.id
92
+ });
93
+ if (result.models == null) {
94
+ throw new Error(`Models not found for graph: ${ctx.arguments.id}`);
95
+ }
96
+ const schema = createSchema(result.models, result.aliases);
97
+ return {
98
+ content: [
99
+ {
100
+ type: 'text',
101
+ text: printSchema(schema)
102
+ }
103
+ ]
104
+ };
105
+ } catch (error) {
106
+ return {
107
+ isError: true,
108
+ content: [
109
+ {
110
+ type: 'text',
111
+ text: `Failed to get GraphQL schema: ${error instanceof Error ? error.message : String(error)}`
112
+ }
113
+ ]
114
+ };
115
+ }
116
+ });
117
+ const graph_query = createTool('Execute a GraphQL query on the given graph ID', {
118
+ type: 'object',
119
+ properties: {
120
+ id: {
121
+ type: 'string'
122
+ },
123
+ query: {
124
+ type: 'string'
125
+ },
126
+ variables: {
127
+ type: 'object'
128
+ }
129
+ },
130
+ required: [
131
+ 'id',
132
+ 'query'
133
+ ],
134
+ additionalProperties: false
135
+ }, async (ctx)=>{
136
+ try {
137
+ const result = await client.queryGraph({
138
+ id: ctx.arguments.id,
139
+ text: ctx.arguments.query,
140
+ variables: ctx.arguments.variables ?? {}
141
+ });
142
+ if (result.errors != null && result.errors.length > 0) {
143
+ return {
144
+ isError: true,
145
+ content: [
146
+ {
147
+ type: 'text',
148
+ text: result.errors.map((e)=>e.toString()).join(', ')
149
+ }
150
+ ],
151
+ structuredContent: {
152
+ errors: result.errors
153
+ }
154
+ };
155
+ }
156
+ return {
157
+ content: [
158
+ {
159
+ type: 'text',
160
+ text: JSON.stringify(result.data)
161
+ }
162
+ ],
163
+ structuredContent: {
164
+ data: result.data
165
+ }
166
+ };
167
+ } catch (error) {
168
+ return {
169
+ isError: true,
170
+ content: [
171
+ {
172
+ type: 'text',
173
+ text: `Failed to execute GraphQL query: ${error instanceof Error ? error.message : String(error)}`
174
+ }
175
+ ]
176
+ };
177
+ }
178
+ });
179
+ const graph_mutate = createTool('Execute a GraphQL mutation on the given graph ID', {
180
+ type: 'object',
181
+ properties: {
182
+ id: {
183
+ type: 'string'
184
+ },
185
+ query: {
186
+ type: 'string'
187
+ },
188
+ variables: {
189
+ type: 'object'
190
+ }
191
+ },
192
+ required: [
193
+ 'id',
194
+ 'query'
195
+ ],
196
+ additionalProperties: false
197
+ }, async (ctx)=>{
198
+ try {
199
+ const result = await client.mutateGraph({
200
+ id: ctx.arguments.id,
201
+ text: ctx.arguments.query,
202
+ variables: ctx.arguments.variables ?? {}
203
+ });
204
+ if (result.errors != null && result.errors.length > 0) {
205
+ return {
206
+ isError: true,
207
+ content: [
208
+ {
209
+ type: 'text',
210
+ text: result.errors.map((e)=>e.toString()).join(', ')
211
+ }
212
+ ],
213
+ structuredContent: {
214
+ errors: result.errors
215
+ }
216
+ };
217
+ }
218
+ return {
219
+ content: [
220
+ {
221
+ type: 'text',
222
+ text: JSON.stringify(result.data)
223
+ }
224
+ ],
225
+ structuredContent: {
226
+ data: result.data
227
+ }
228
+ };
229
+ } catch (error) {
230
+ return {
231
+ isError: true,
232
+ content: [
233
+ {
234
+ type: 'text',
235
+ text: `Failed to execute GraphQL mutation: ${error instanceof Error ? error.message : String(error)}`
236
+ }
237
+ ]
238
+ };
239
+ }
240
+ });
241
+ return {
242
+ graph_list,
243
+ graph_info,
244
+ graph_schema,
245
+ graph_query,
246
+ graph_mutate
247
+ };
248
+ }
@@ -0,0 +1,3 @@
1
+ export { createClusterTools } from './cluster.js';
2
+ export { createGraphTools } from './graph.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAA;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA"}
@@ -0,0 +1,2 @@
1
+ export { createClusterTools } from './cluster.js';
2
+ export { createGraphTools } from './graph.js';
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "@kubun/mcp",
3
+ "version": "0.1.0",
4
+ "description": "MCP server for Kubun",
5
+ "keywords": [],
6
+ "type": "module",
7
+ "main": "lib/index.js",
8
+ "types": "lib/index.d.ts",
9
+ "exports": {
10
+ ".": "./lib/index.js",
11
+ "./run": "./lib/run.js"
12
+ },
13
+ "bin": {
14
+ "kubun-mcp": "./lib/run.js"
15
+ },
16
+ "files": [
17
+ "lib/*"
18
+ ],
19
+ "sideEffects": false,
20
+ "dependencies": {
21
+ "@enkaku/token": "0.12.3",
22
+ "@mokei/context-server": "^0.4.0",
23
+ "graphql": "^16.12.0",
24
+ "@kubun/db": "^0.4.0",
25
+ "@kubun/db-postgres": "^0.4.0",
26
+ "@kubun/db-sqlite": "^0.4.0",
27
+ "@kubun/http-client": "^0.4.0",
28
+ "@kubun/protocol": "^0.4.0",
29
+ "@kubun/graphql": "^0.4.2",
30
+ "@kubun/server": "^0.4.1"
31
+ },
32
+ "devDependencies": {
33
+ "@enkaku/transport": "0.12.0",
34
+ "@mokei/context-client": "^0.4.0",
35
+ "@mokei/context-protocol": "^0.4.0",
36
+ "@kubun/client": "^0.4.0"
37
+ },
38
+ "scripts": {
39
+ "build:clean": "del lib",
40
+ "build:js": "swc src -d ./lib --config-file ../../swc.json --strip-leading-paths",
41
+ "build:types": "tsc --emitDeclarationOnly --skipLibCheck",
42
+ "build": "pnpm run build:clean && pnpm run build:js && pnpm run build:types",
43
+ "test:types": "tsc --noEmit",
44
+ "test:unit": "vitest run",
45
+ "test": "pnpm run test:types && pnpm run test:unit"
46
+ }
47
+ }