@kubun/mcp 0.4.2 → 0.5.1
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/lib/client.d.ts +2 -3
- package/lib/client.js +1 -31
- package/lib/config.d.ts +2 -3
- package/lib/config.js +1 -45
- package/lib/index.d.ts +0 -1
- package/lib/index.js +1 -2
- package/lib/prompts/data-model-designer.d.ts +0 -1
- package/lib/prompts/data-model-designer.js +2 -2
- package/lib/prompts/index.d.ts +0 -1
- package/lib/prompts/index.js +1 -19
- package/lib/run.d.ts +0 -1
- package/lib/run.js +1 -18
- package/lib/tools/cluster.d.ts +0 -1
- package/lib/tools/cluster.js +1 -76
- package/lib/tools/graph.d.ts +0 -1
- package/lib/tools/graph.js +1 -273
- package/lib/tools/index.d.ts +0 -1
- package/lib/tools/index.js +1 -2
- package/package.json +12 -12
- package/lib/client.d.ts.map +0 -1
- package/lib/config.d.ts.map +0 -1
- package/lib/index.d.ts.map +0 -1
- package/lib/prompts/data-model-designer.d.ts.map +0 -1
- package/lib/prompts/index.d.ts.map +0 -1
- package/lib/run.d.ts.map +0 -1
- package/lib/tools/cluster.d.ts.map +0 -1
- package/lib/tools/graph.d.ts.map +0 -1
- package/lib/tools/index.d.ts.map +0 -1
package/lib/client.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type SigningIdentity } from '@enkaku/token';
|
|
2
2
|
import type { KubunClient } from '@kubun/client';
|
|
3
3
|
export type ClientConfig = {
|
|
4
4
|
type: 'memory';
|
|
@@ -14,7 +14,6 @@ export type ClientConfig = {
|
|
|
14
14
|
serverID?: string;
|
|
15
15
|
};
|
|
16
16
|
export type ClientParams = ClientConfig & {
|
|
17
|
-
|
|
17
|
+
identity?: SigningIdentity;
|
|
18
18
|
};
|
|
19
19
|
export declare function createClient(params: ClientParams): KubunClient;
|
|
20
|
-
//# sourceMappingURL=client.d.ts.map
|
package/lib/client.js
CHANGED
|
@@ -1,31 +1 @@
|
|
|
1
|
-
import {
|
|
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
|
-
}
|
|
1
|
+
import{randomIdentity as e}from"@enkaku/token";import{KubunDB as t}from"@kubun/db";import{NodeSQLiteAdapter as r}from"@kubun/db-node-sqlite";import{PostgresAdapter as n}from"@kubun/db-postgres";import{HTTPClient as o}from"@kubun/http-client";import{KubunServer as u}from"@kubun/server";export function createClient(p){let i=p.identity??e();return"http"===p.type?new o({identity:i,serverID:p.serverID,url:p.url}):new u({db:new t({adapter:"postgres"===p.type?new n({url:p.url}):new r({database:"sqlite"===p.type?p.path:":memory:"})}),identity:i}).createClient({identity:i})}
|
package/lib/config.d.ts
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { SigningIdentity } from '@enkaku/token';
|
|
2
2
|
import type { ServerConfig } from '@mokei/context-server';
|
|
3
3
|
export type MCPConfig = {
|
|
4
4
|
connect?: string;
|
|
5
5
|
database?: string;
|
|
6
|
-
|
|
6
|
+
identity?: SigningIdentity;
|
|
7
7
|
};
|
|
8
8
|
export declare function createConfig(config?: MCPConfig): ServerConfig;
|
|
9
|
-
//# sourceMappingURL=config.d.ts.map
|
package/lib/config.js
CHANGED
|
@@ -1,45 +1 @@
|
|
|
1
|
-
import {
|
|
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
|
-
}
|
|
1
|
+
import{createClient as t}from"./client.js";import{prompts as e}from"./prompts/index.js";import{createClusterTools as i}from"./tools/cluster.js";import{createGraphTools as o}from"./tools/graph.js";export function createConfig(n={}){var r;let s=t(null!=(r=n).connect?{type:"http",url:r.connect,identity:r.identity}:null!=r.database?r.database.startsWith("postgres://")?{type:"postgres",url:r.database,identity:r.identity}:{type:"sqlite",path:r.database,identity:r.identity}:{type:"memory",identity:r.identity}),a=i(s),p=o(s);return{name:"kubun",version:"0.1.0",prompts:e,tools:{...a,...p}}}
|
package/lib/index.d.ts
CHANGED
package/lib/index.js
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
export
|
|
2
|
-
export { createConfig } from './config.js';
|
|
1
|
+
export{createClient}from"./client.js";export{createConfig}from"./config.js";
|
|
@@ -1,2 +1 @@
|
|
|
1
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**Model Immutability:**\n- Once a model is created and in use, its schema cannot be modified\n- Relations defined in `fieldsMeta` are permanent and cannot be updated to point to different models\n- Plan for extensibility upfront by using interface-based relations\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 `model` value when a field can reference any document\n\n**Example - Field that can link to any document:**\n```json\n{\n \"fieldsMeta\": {\n \"linkedItem\": {\n \"type\": \"document\",\n \"model\": null\n }\n }\n}\n```\n\n---\n\n## Future-Proofing Relations with Domain Interfaces\n\n### The Problem\n\nBecause models are immutable, relations defined in `fieldsMeta` cannot be changed after creation. If you define a relation pointing directly to a concrete model (e.g., `Task`), you cannot later extend it to include new model variants (e.g., `RecurringTask`, `MilestoneTask`).\n\n### The Solution: Domain Interface Layer\n\nCreate **domain-specific interfaces** that define the minimum contract for a category of entities. Point relations to these interfaces instead of concrete models.\n\n**Interface Hierarchy Pattern:**\n```\nBehavioral Interface (e.g., Schedulable, Completable)\n \u2193 implements\nDomain Interface (e.g., TaskKind, EventKind, ProjectKind)\n \u2193 implements\nConcrete Models (e.g., Task, RecurringTask, SubTask)\n```\n\n### When to Apply This Pattern\n\nCreate a domain interface when:\n\n1. **Multiple variants are foreseeable** - The entity could have specialized versions (e.g., tasks \u2192 recurring tasks, subtasks, milestone tasks)\n2. **Other models will relate to it** - The entity will be referenced by other models via `fieldsMeta`\n3. **The domain has a stable core contract** - There's a clear minimum set of fields that all variants would share\n\n### Domain Interface Design Guidelines\n\nA domain interface should:\n\n1. **Implement relevant behavioral interfaces** (Schedulable, Completable, etc.)\n2. **Define the minimum viable field set** that all variants must support\n3. **Include fields essential for querying and display** (typically: title/name, status indicators)\n4. **Use `additionalProperties: true`** to allow concrete models to extend it\n5. **Be named with a `Kind` suffix** (e.g., `TaskKind`, `EventKind`, `NoteKind`)\n\n### Example: Task Domain with Future-Proofing\n\n**Without future-proofing (problematic):**\n```\nCompletable (interface)\n \u2193\nTask (concrete) \u2190 Reminder.linkedTask points here\n \u2717 Cannot later include RecurringTask in this relation\n```\n\n**With future-proofing (recommended):**\n```\nCompletable (interface)\n \u2193\nTaskKind (domain interface) \u2190 Reminder.linkedTask points here\n \u2193 \u2713 Automatically includes all TaskKind implementations\nTask (concrete)\nRecurringTask (concrete) \u2190 Can be added later\nSubTask (concrete) \u2190 Can be added later\n```\n\n### Complete Example\n\n**#0 - Behavioral Interface:**\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**#1 - Domain Interface (future-proofing layer):**\n```json\n{\n \"name\": \"TaskKind\",\n \"version\": \"1.0\",\n \"interfaces\": [\"#0\"],\n \"behavior\": \"interface\",\n \"schema\": {\n \"type\": \"object\",\n \"properties\": {\n \"title\": { \"$ref\": \"#/definitions/Title\" },\n \"completed\": { \"$ref\": \"#/definitions/Completed\" },\n \"completedAt\": { \"$ref\": \"#/definitions/DateTime\" },\n \"priority\": { \"$ref\": \"#/definitions/Priority\" }\n },\n \"required\": [\"title\", \"completed\", \"priority\"],\n \"additionalProperties\": true,\n \"definitions\": {\n \"Title\": { \"type\": \"string\", \"title\": \"Title\", \"minLength\": 1, \"maxLength\": 200 },\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 }\n },\n \"fieldsMeta\": {}\n}\n```\n\n**#2 - Concrete Model:**\n```json\n{\n \"name\": \"Task\",\n \"version\": \"1.0\",\n \"interfaces\": [\"#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 \"dueDate\": { \"$ref\": \"#/definitions/DateTime\" },\n \"taskList\": { \"$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 \"taskList\": { \"type\": \"document\", \"model\": \"#5\" }\n }\n}\n```\n\n**#3 - Model with relation to domain interface:**\n```json\n{\n \"name\": \"Reminder\",\n \"version\": \"1.0\",\n \"interfaces\": [],\n \"behavior\": \"default\",\n \"schema\": {\n \"type\": \"object\",\n \"properties\": {\n \"title\": { \"$ref\": \"#/definitions/Title\" },\n \"linkedTask\": { \"$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 \"linkedTask\": {\n \"type\": \"document\",\n \"model\": \"#1\"\n }\n }\n}\n```\n\n**Note:** The `Reminder.linkedTask` relation points to `#1` (TaskKind interface), not `#2` (Task concrete model). This means:\n- Current `Task` documents can be linked \u2713\n- Future `RecurringTask` documents implementing `TaskKind` can also be linked \u2713\n- Future `SubTask` documents implementing `TaskKind` can also be linked \u2713\n\n### Relation Target Decision Guide\n\n| Scenario | Relation Target | Example |\n|----------|-----------------|---------|\n| Only one model type will ever exist | Concrete model | User settings \u2192 Settings model |\n| Multiple variants are likely | Domain interface | Reminder \u2192 TaskKind interface |\n| Any document type should work | `null` (Node) | Attachment \u2192 any document |\n| Specific behavioral capability needed | Behavioral interface | Calendar view \u2192 Schedulable |\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**Best Practice:** When defining relations, prefer pointing to domain interfaces (e.g., `TaskKind`) over concrete models (e.g., `Task`) to maintain extensibility.\n\n**Example:**\n```json\n{\n \"fieldsMeta\": {\n \"parentProject\": {\n \"type\": \"document\",\n \"model\": \"#3\"\n },\n \"linkedTask\": {\n \"type\": \"document\",\n \"model\": \"#1\"\n },\n \"attachment\": {\n \"type\": \"document\",\n \"model\": 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| Domain interface names | PascalCase with `Kind` suffix | `TaskKind`, `EventKind`, `NoteKind` |\n| Behavioral interface names | PascalCase adjective/capability | `Schedulable`, `Completable`, `Taggable` |\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### Behavioral Interface\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### Domain Interface (Future-Proofing Layer)\n```json\n{\n \"name\": \"TaskKind\",\n \"version\": \"1.0\",\n \"interfaces\": [\"#0\"],\n \"behavior\": \"interface\",\n \"schema\": {\n \"type\": \"object\",\n \"properties\": {\n \"title\": { \"$ref\": \"#/definitions/Title\" },\n \"completed\": { \"$ref\": \"#/definitions/Completed\" },\n \"completedAt\": { \"$ref\": \"#/definitions/DateTime\" },\n \"priority\": { \"$ref\": \"#/definitions/Priority\" }\n },\n \"required\": [\"title\", \"completed\", \"priority\"],\n \"additionalProperties\": true,\n \"definitions\": {\n \"Title\": { \"type\": \"string\", \"title\": \"Title\", \"minLength\": 1, \"maxLength\": 200 },\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 }\n },\n \"fieldsMeta\": {}\n}\n```\n\n**Note:** Domain interfaces define the minimum contract for a category of entities and should be used as relation targets.\n\n### Concrete Model (Implementing Domain Interface)\n```json\n{\n \"name\": \"Task\",\n \"version\": \"1.0\",\n \"interfaces\": [\"#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 \"dueDate\": { \"$ref\": \"#/definitions/DateTime\" },\n \"taskList\": { \"$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 \"taskList\": { \"type\": \"document\", \"model\": \"#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 Relation to Domain Interface\n```json\n{\n \"name\": \"Reminder\",\n \"version\": \"1.0\",\n \"interfaces\": [],\n \"behavior\": \"default\",\n \"schema\": {\n \"type\": \"object\",\n \"properties\": {\n \"title\": { \"$ref\": \"#/definitions/Title\" },\n \"linkedTask\": { \"$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 \"linkedTask\": { \"type\": \"document\", \"model\": \"#1\" }\n }\n}\n```\n\n**Note:** The relation points to `TaskKind` (#1), not `Task` (#2), enabling future task variants to be linked.\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. **Create domain interfaces for extensible entities** - use `Kind` suffix (e.g., `TaskKind`) when multiple variants are foreseeable\n6. **Point relations to domain interfaces, not concrete models** - ensures future model variants can participate in existing relations\n7. **Ask clarifying questions** about requirements and expected future variants\n8. **Choose appropriate behavior** (`default` / `interface` / `unique`)\n9. **Use predefined types** when they match the use case\n10. **Define clear field relationships** using `fieldsMeta`\n11. **Include reasonable validation** (lengths, patterns, ranges)\n12. **Follow naming conventions** strictly\n13. **Make required fields explicit**\n14. **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. **Behavioral interfaces** (indices 0, 1, 2, ...) - Abstract capabilities (Schedulable, Completable, Taggable)\n2. **Domain interfaces** - Entity-type contracts with `Kind` suffix (TaskKind, EventKind, NoteKind)\n3. **Shared/referenced models** (e.g., Tag, Category) - Models referenced by many others\n4. **Concrete domain models** - Implementations grouped by domain\n\n**Example cluster structure:**\n```\n#0 Schedulable (behavioral interface)\n#1 Completable (behavioral interface)\n#2 Prioritizable (behavioral interface)\n#3 Taggable (behavioral interface)\n#4 TaskKind (domain interface, implements #1, #2)\n#5 EventKind (domain interface, implements #0)\n#6 Tag (shared model, referenced by Taggable implementations)\n#7 Task (concrete, implements #4, #3)\n#8 RecurringTask (concrete, implements #4, #3)\n#9 Event (concrete, implements #5, #3)\n#10 Reminder (concrete, relates to #4 for future-proof task linking)\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
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export const KUBUN_PROMPT_INSTRUCTIONS
|
|
1
|
+
export const KUBUN_PROMPT_INSTRUCTIONS=`# Kubun Protocol Data Model Generator
|
|
2
2
|
|
|
3
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
4
|
|
|
@@ -612,4 +612,4 @@ When generating a model cluster, organize models in this order:
|
|
|
612
612
|
|
|
613
613
|
## Response Format
|
|
614
614
|
|
|
615
|
-
Always generate models as a JSON array, even when a single model is needed. Validate that your output follows the specification exactly.`;
|
|
615
|
+
Always generate models as a JSON array, even when a single model is needed. Validate that your output follows the specification exactly.`;
|
package/lib/prompts/index.d.ts
CHANGED
package/lib/prompts/index.js
CHANGED
|
@@ -1,19 +1 @@
|
|
|
1
|
-
import
|
|
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
|
-
};
|
|
1
|
+
import{KUBUN_PROMPT_INSTRUCTIONS as e}from"./data-model-designer.js";export const prompts={"data-model-designer":{description:"Instructions to help design a data model following the Kubun protocol specification",handler:()=>({messages:[{role:"user",content:{type:"text",text:e}}]})}};
|
package/lib/run.d.ts
CHANGED
package/lib/run.js
CHANGED
|
@@ -1,19 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
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);
|
|
2
|
+
import{parseArgs as e}from"node:util";import{serveProcess as o}from"@mokei/context-server";import{createConfig as t}from"./config.js";let n=e({options:{connect:{type:"string"},db:{type:"string"}}});o(t({connect:n.values.connect,database:n.values.db}));
|
package/lib/tools/cluster.d.ts
CHANGED
package/lib/tools/cluster.js
CHANGED
|
@@ -1,76 +1 @@
|
|
|
1
|
-
import
|
|
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
|
-
name: {
|
|
45
|
-
type: 'string'
|
|
46
|
-
}
|
|
47
|
-
},
|
|
48
|
-
required: [
|
|
49
|
-
'clusters'
|
|
50
|
-
],
|
|
51
|
-
additionalProperties: false
|
|
52
|
-
}, async (ctx)=>{
|
|
53
|
-
const result = await client.deployGraph({
|
|
54
|
-
clusters: ctx.arguments.clusters,
|
|
55
|
-
id: ctx.arguments.id,
|
|
56
|
-
name: ctx.arguments.name
|
|
57
|
-
});
|
|
58
|
-
return {
|
|
59
|
-
content: [
|
|
60
|
-
{
|
|
61
|
-
type: 'text',
|
|
62
|
-
text: `Clusters deployed to graph "${result.id}"`
|
|
63
|
-
}
|
|
64
|
-
],
|
|
65
|
-
structuredContent: {
|
|
66
|
-
id: result.id,
|
|
67
|
-
record: result.record,
|
|
68
|
-
aliases: result.aliases
|
|
69
|
-
}
|
|
70
|
-
};
|
|
71
|
-
});
|
|
72
|
-
return {
|
|
73
|
-
create_cluster,
|
|
74
|
-
deploy_clusters
|
|
75
|
-
};
|
|
76
|
-
}
|
|
1
|
+
import{ClusterBuilder as e,clusterModel as t}from"@kubun/protocol";import{createTool as r}from"@mokei/context-server";export function createClusterTools(s){return{create_cluster:r("Create a new cluster from model definitions",{type:"object",properties:{models:{type:"array",items:{type:"object"}}},required:["models"],additionalProperties:!1},async t=>{let r=new e;return r.addAll(t.arguments.models),{content:[{type:"text",text:"Cluster created"}],structuredContent:{cluster:r.build()}}}),deploy_clusters:r("Deploy clusters to the Kubun backend",{type:"object",properties:{clusters:{type:"array",items:t},id:{type:"string"},name:{type:"string"}},required:["clusters"],additionalProperties:!1},async e=>{let t=await s.deployGraph({clusters:e.arguments.clusters,id:e.arguments.id,name:e.arguments.name});return{content:[{type:"text",text:`Clusters deployed to graph "${t.id}"`}],structuredContent:{id:t.id,record:t.record,aliases:t.aliases}}})}}
|
package/lib/tools/graph.d.ts
CHANGED
package/lib/tools/graph.js
CHANGED
|
@@ -1,273 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { createTool } from '@mokei/context-server';
|
|
3
|
-
import { printSchema } from 'graphql';
|
|
4
|
-
function getModelsInfo(result) {
|
|
5
|
-
const aliases = result.aliases ?? {};
|
|
6
|
-
return Object.entries(result.record).reduce((acc, [id, model])=>{
|
|
7
|
-
const alias = aliases[id] ?? model.name;
|
|
8
|
-
acc[alias] = {
|
|
9
|
-
id,
|
|
10
|
-
behavior: model.behavior,
|
|
11
|
-
interfaces: model.interfaces,
|
|
12
|
-
fields: Object.keys(model.schema.properties)
|
|
13
|
-
};
|
|
14
|
-
return acc;
|
|
15
|
-
}, {});
|
|
16
|
-
}
|
|
17
|
-
export function createGraphTools(client) {
|
|
18
|
-
const graph_list = createTool('List all available graphs', {
|
|
19
|
-
type: 'object'
|
|
20
|
-
}, async ()=>{
|
|
21
|
-
const result = await client.listGraphs();
|
|
22
|
-
const graphs = result.graphs.map((graph)=>`${graph.name} (${graph.id})`).join(', ');
|
|
23
|
-
return {
|
|
24
|
-
content: [
|
|
25
|
-
{
|
|
26
|
-
type: 'text',
|
|
27
|
-
text: graphs === '' ? 'No graphs available' : `Available graphs: ${graphs}`
|
|
28
|
-
}
|
|
29
|
-
],
|
|
30
|
-
structuredContent: {
|
|
31
|
-
graphs: result.graphs
|
|
32
|
-
}
|
|
33
|
-
};
|
|
34
|
-
});
|
|
35
|
-
const graph_info = createTool('Get information about a specific graph', {
|
|
36
|
-
type: 'object',
|
|
37
|
-
properties: {
|
|
38
|
-
id: {
|
|
39
|
-
type: 'string'
|
|
40
|
-
}
|
|
41
|
-
},
|
|
42
|
-
required: [
|
|
43
|
-
'id'
|
|
44
|
-
],
|
|
45
|
-
additionalProperties: false
|
|
46
|
-
}, async (ctx)=>{
|
|
47
|
-
try {
|
|
48
|
-
const result = await client.loadGraph({
|
|
49
|
-
id: ctx.arguments.id
|
|
50
|
-
});
|
|
51
|
-
const info = getModelsInfo(result);
|
|
52
|
-
return {
|
|
53
|
-
content: [
|
|
54
|
-
{
|
|
55
|
-
type: 'text',
|
|
56
|
-
text: JSON.stringify(info)
|
|
57
|
-
}
|
|
58
|
-
],
|
|
59
|
-
structuredContent: info
|
|
60
|
-
};
|
|
61
|
-
} catch (error) {
|
|
62
|
-
return {
|
|
63
|
-
isError: true,
|
|
64
|
-
content: [
|
|
65
|
-
{
|
|
66
|
-
type: 'text',
|
|
67
|
-
text: `Failed to get GraphQL schema: ${error instanceof Error ? error.message : String(error)}`
|
|
68
|
-
}
|
|
69
|
-
]
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
});
|
|
73
|
-
const graph_schema = createTool('Get the GraphQL schema for the given graph ID. Supports selective generation to reduce schema size for LLM context.', {
|
|
74
|
-
type: 'object',
|
|
75
|
-
properties: {
|
|
76
|
-
id: {
|
|
77
|
-
type: 'string',
|
|
78
|
-
description: 'The graph ID'
|
|
79
|
-
},
|
|
80
|
-
onlyModels: {
|
|
81
|
-
type: 'array',
|
|
82
|
-
items: {
|
|
83
|
-
type: 'string'
|
|
84
|
-
},
|
|
85
|
-
description: 'Optional array of model IDs or aliases to include in schema. If not provided, all models are included.'
|
|
86
|
-
},
|
|
87
|
-
includeInterfaceDependencies: {
|
|
88
|
-
type: 'boolean',
|
|
89
|
-
description: 'Whether to include interface dependencies (default: true)'
|
|
90
|
-
},
|
|
91
|
-
includeRelationDependencies: {
|
|
92
|
-
type: 'boolean',
|
|
93
|
-
description: 'Whether to include relation dependencies (default: true)'
|
|
94
|
-
},
|
|
95
|
-
includeMutations: {
|
|
96
|
-
type: 'boolean',
|
|
97
|
-
description: 'Whether to include mutations in the schema (default: true)'
|
|
98
|
-
},
|
|
99
|
-
includeSubscriptions: {
|
|
100
|
-
type: 'boolean',
|
|
101
|
-
description: 'Whether to include subscriptions in the schema (default: true)'
|
|
102
|
-
}
|
|
103
|
-
},
|
|
104
|
-
required: [
|
|
105
|
-
'id'
|
|
106
|
-
],
|
|
107
|
-
additionalProperties: false
|
|
108
|
-
}, async (ctx)=>{
|
|
109
|
-
try {
|
|
110
|
-
const result = await client.loadGraph({
|
|
111
|
-
id: ctx.arguments.id
|
|
112
|
-
});
|
|
113
|
-
const schema = createSchema({
|
|
114
|
-
record: result.record,
|
|
115
|
-
aliases: result.aliases,
|
|
116
|
-
onlyModels: ctx.arguments.onlyModels,
|
|
117
|
-
includeInterfaceDependencies: ctx.arguments.includeInterfaceDependencies,
|
|
118
|
-
includeRelationDependencies: ctx.arguments.includeRelationDependencies,
|
|
119
|
-
includeMutations: ctx.arguments.includeMutations,
|
|
120
|
-
includeSubscriptions: ctx.arguments.includeSubscriptions
|
|
121
|
-
});
|
|
122
|
-
return {
|
|
123
|
-
content: [
|
|
124
|
-
{
|
|
125
|
-
type: 'text',
|
|
126
|
-
text: printSchema(schema)
|
|
127
|
-
}
|
|
128
|
-
]
|
|
129
|
-
};
|
|
130
|
-
} catch (error) {
|
|
131
|
-
return {
|
|
132
|
-
isError: true,
|
|
133
|
-
content: [
|
|
134
|
-
{
|
|
135
|
-
type: 'text',
|
|
136
|
-
text: `Failed to get GraphQL schema: ${error instanceof Error ? error.message : String(error)}`
|
|
137
|
-
}
|
|
138
|
-
]
|
|
139
|
-
};
|
|
140
|
-
}
|
|
141
|
-
});
|
|
142
|
-
const graph_query = createTool('Execute a GraphQL query on the given graph ID', {
|
|
143
|
-
type: 'object',
|
|
144
|
-
properties: {
|
|
145
|
-
id: {
|
|
146
|
-
type: 'string'
|
|
147
|
-
},
|
|
148
|
-
query: {
|
|
149
|
-
type: 'string'
|
|
150
|
-
},
|
|
151
|
-
variables: {
|
|
152
|
-
type: 'object'
|
|
153
|
-
}
|
|
154
|
-
},
|
|
155
|
-
required: [
|
|
156
|
-
'id',
|
|
157
|
-
'query'
|
|
158
|
-
],
|
|
159
|
-
additionalProperties: false
|
|
160
|
-
}, async (ctx)=>{
|
|
161
|
-
try {
|
|
162
|
-
const result = await client.queryGraph({
|
|
163
|
-
id: ctx.arguments.id,
|
|
164
|
-
text: ctx.arguments.query,
|
|
165
|
-
variables: ctx.arguments.variables ?? {}
|
|
166
|
-
});
|
|
167
|
-
if (result.errors != null && result.errors.length > 0) {
|
|
168
|
-
return {
|
|
169
|
-
isError: true,
|
|
170
|
-
content: [
|
|
171
|
-
{
|
|
172
|
-
type: 'text',
|
|
173
|
-
text: result.errors.map((e)=>e.toString()).join(', ')
|
|
174
|
-
}
|
|
175
|
-
],
|
|
176
|
-
structuredContent: {
|
|
177
|
-
errors: result.errors
|
|
178
|
-
}
|
|
179
|
-
};
|
|
180
|
-
}
|
|
181
|
-
return {
|
|
182
|
-
content: [
|
|
183
|
-
{
|
|
184
|
-
type: 'text',
|
|
185
|
-
text: JSON.stringify(result.data)
|
|
186
|
-
}
|
|
187
|
-
],
|
|
188
|
-
structuredContent: {
|
|
189
|
-
data: result.data
|
|
190
|
-
}
|
|
191
|
-
};
|
|
192
|
-
} catch (error) {
|
|
193
|
-
return {
|
|
194
|
-
isError: true,
|
|
195
|
-
content: [
|
|
196
|
-
{
|
|
197
|
-
type: 'text',
|
|
198
|
-
text: `Failed to execute GraphQL query: ${error instanceof Error ? error.message : String(error)}`
|
|
199
|
-
}
|
|
200
|
-
]
|
|
201
|
-
};
|
|
202
|
-
}
|
|
203
|
-
});
|
|
204
|
-
const graph_mutate = createTool('Execute a GraphQL mutation on the given graph ID', {
|
|
205
|
-
type: 'object',
|
|
206
|
-
properties: {
|
|
207
|
-
id: {
|
|
208
|
-
type: 'string'
|
|
209
|
-
},
|
|
210
|
-
query: {
|
|
211
|
-
type: 'string'
|
|
212
|
-
},
|
|
213
|
-
variables: {
|
|
214
|
-
type: 'object'
|
|
215
|
-
}
|
|
216
|
-
},
|
|
217
|
-
required: [
|
|
218
|
-
'id',
|
|
219
|
-
'query'
|
|
220
|
-
],
|
|
221
|
-
additionalProperties: false
|
|
222
|
-
}, async (ctx)=>{
|
|
223
|
-
try {
|
|
224
|
-
const result = await client.mutateGraph({
|
|
225
|
-
id: ctx.arguments.id,
|
|
226
|
-
text: ctx.arguments.query,
|
|
227
|
-
variables: ctx.arguments.variables ?? {}
|
|
228
|
-
});
|
|
229
|
-
if (result.errors != null && result.errors.length > 0) {
|
|
230
|
-
return {
|
|
231
|
-
isError: true,
|
|
232
|
-
content: [
|
|
233
|
-
{
|
|
234
|
-
type: 'text',
|
|
235
|
-
text: result.errors.map((e)=>e.toString()).join(', ')
|
|
236
|
-
}
|
|
237
|
-
],
|
|
238
|
-
structuredContent: {
|
|
239
|
-
errors: result.errors
|
|
240
|
-
}
|
|
241
|
-
};
|
|
242
|
-
}
|
|
243
|
-
return {
|
|
244
|
-
content: [
|
|
245
|
-
{
|
|
246
|
-
type: 'text',
|
|
247
|
-
text: JSON.stringify(result.data)
|
|
248
|
-
}
|
|
249
|
-
],
|
|
250
|
-
structuredContent: {
|
|
251
|
-
data: result.data
|
|
252
|
-
}
|
|
253
|
-
};
|
|
254
|
-
} catch (error) {
|
|
255
|
-
return {
|
|
256
|
-
isError: true,
|
|
257
|
-
content: [
|
|
258
|
-
{
|
|
259
|
-
type: 'text',
|
|
260
|
-
text: `Failed to execute GraphQL mutation: ${error instanceof Error ? error.message : String(error)}`
|
|
261
|
-
}
|
|
262
|
-
]
|
|
263
|
-
};
|
|
264
|
-
}
|
|
265
|
-
});
|
|
266
|
-
return {
|
|
267
|
-
graph_list,
|
|
268
|
-
graph_info,
|
|
269
|
-
graph_schema,
|
|
270
|
-
graph_query,
|
|
271
|
-
graph_mutate
|
|
272
|
-
};
|
|
273
|
-
}
|
|
1
|
+
import{createSchema as e}from"@kubun/graphql";import{createTool as t}from"@mokei/context-server";import{printSchema as r}from"graphql";export function createGraphTools(n){let i=t("List all available graphs",{type:"object"},async()=>{let e=await n.listGraphs(),t=e.graphs.map(e=>`${e.name} (${e.id})`).join(", ");return{content:[{type:"text",text:""===t?"No graphs available":`Available graphs: ${t}`}],structuredContent:{graphs:e.graphs}}}),a=t("Get information about a specific graph",{type:"object",properties:{id:{type:"string"}},required:["id"],additionalProperties:!1},async e=>{try{var t;let r,i=(r=(t=await n.loadGraph({id:e.arguments.id})).aliases??{},Object.entries(t.record).reduce((e,[t,n])=>(e[r[t]??n.name]={id:t,behavior:n.behavior,interfaces:n.interfaces,fields:Object.keys(n.schema.properties)},e),{}));return{content:[{type:"text",text:JSON.stringify(i)}],structuredContent:i}}catch(e){return{isError:!0,content:[{type:"text",text:`Failed to get GraphQL schema: ${e instanceof Error?e.message:String(e)}`}]}}}),o=t("Get the GraphQL schema for the given graph ID. Supports selective generation to reduce schema size for LLM context.",{type:"object",properties:{id:{type:"string",description:"The graph ID"},onlyModels:{type:"array",items:{type:"string"},description:"Optional array of model IDs or aliases to include in schema. If not provided, all models are included."},includeInterfaceDependencies:{type:"boolean",description:"Whether to include interface dependencies (default: true)"},includeRelationDependencies:{type:"boolean",description:"Whether to include relation dependencies (default: true)"},includeMutations:{type:"boolean",description:"Whether to include mutations in the schema (default: true)"},includeSubscriptions:{type:"boolean",description:"Whether to include subscriptions in the schema (default: true)"}},required:["id"],additionalProperties:!1},async t=>{try{let i=await n.loadGraph({id:t.arguments.id}),a=e({record:i.record,aliases:i.aliases,onlyModels:t.arguments.onlyModels,includeInterfaceDependencies:t.arguments.includeInterfaceDependencies,includeRelationDependencies:t.arguments.includeRelationDependencies,includeMutations:t.arguments.includeMutations,includeSubscriptions:t.arguments.includeSubscriptions});return{content:[{type:"text",text:r(a)}]}}catch(e){return{isError:!0,content:[{type:"text",text:`Failed to get GraphQL schema: ${e instanceof Error?e.message:String(e)}`}]}}});return{graph_list:i,graph_info:a,graph_schema:o,graph_query:t("Execute a GraphQL query on the given graph ID",{type:"object",properties:{id:{type:"string"},query:{type:"string"},variables:{type:"object"}},required:["id","query"],additionalProperties:!1},async e=>{try{let t=await n.queryGraph({id:e.arguments.id,text:e.arguments.query,variables:e.arguments.variables??{}});if(null!=t.errors&&t.errors.length>0)return{isError:!0,content:[{type:"text",text:t.errors.map(e=>e.toString()).join(", ")}],structuredContent:{errors:t.errors}};return{content:[{type:"text",text:JSON.stringify(t.data)}],structuredContent:{data:t.data}}}catch(e){return{isError:!0,content:[{type:"text",text:`Failed to execute GraphQL query: ${e instanceof Error?e.message:String(e)}`}]}}}),graph_mutate:t("Execute a GraphQL mutation on the given graph ID",{type:"object",properties:{id:{type:"string"},query:{type:"string"},variables:{type:"object"}},required:["id","query"],additionalProperties:!1},async e=>{try{let t=await n.mutateGraph({id:e.arguments.id,text:e.arguments.query,variables:e.arguments.variables??{}});if(null!=t.errors&&t.errors.length>0)return{isError:!0,content:[{type:"text",text:t.errors.map(e=>e.toString()).join(", ")}],structuredContent:{errors:t.errors}};return{content:[{type:"text",text:JSON.stringify(t.data)}],structuredContent:{data:t.data}}}catch(e){return{isError:!0,content:[{type:"text",text:`Failed to execute GraphQL mutation: ${e instanceof Error?e.message:String(e)}`}]}}})}}
|
package/lib/tools/index.d.ts
CHANGED
package/lib/tools/index.js
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
export
|
|
2
|
-
export { createGraphTools } from './graph.js';
|
|
1
|
+
export{createClusterTools}from"./cluster.js";export{createGraphTools}from"./graph.js";
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kubun/mcp",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
3
|
+
"version": "0.5.1",
|
|
4
|
+
"license": "see LICENSE.md",
|
|
5
5
|
"keywords": [],
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "lib/index.js",
|
|
@@ -18,22 +18,22 @@
|
|
|
18
18
|
],
|
|
19
19
|
"sideEffects": false,
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"@enkaku/token": "0.
|
|
21
|
+
"@enkaku/token": "0.13.0",
|
|
22
22
|
"@mokei/context-server": "^0.5.0",
|
|
23
23
|
"graphql": "^16.12.0",
|
|
24
|
-
"@kubun/db
|
|
25
|
-
"@kubun/db-
|
|
26
|
-
"@kubun/
|
|
27
|
-
"@kubun/
|
|
28
|
-
"@kubun/
|
|
29
|
-
"@kubun/graphql": "^0.
|
|
30
|
-
"@kubun/
|
|
24
|
+
"@kubun/db": "^0.5.1",
|
|
25
|
+
"@kubun/db-postgres": "^0.5.0",
|
|
26
|
+
"@kubun/server": "^0.5.0",
|
|
27
|
+
"@kubun/protocol": "^0.5.3",
|
|
28
|
+
"@kubun/http-client": "^0.5.0",
|
|
29
|
+
"@kubun/graphql": "^0.5.0",
|
|
30
|
+
"@kubun/db-node-sqlite": "^0.5.0"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
|
-
"@enkaku/transport": "0.
|
|
33
|
+
"@enkaku/transport": "0.13.1",
|
|
34
34
|
"@mokei/context-client": "^0.5.0",
|
|
35
35
|
"@mokei/context-protocol": "^0.5.0",
|
|
36
|
-
"@kubun/client": "^0.
|
|
36
|
+
"@kubun/client": "^0.5.0"
|
|
37
37
|
},
|
|
38
38
|
"scripts": {
|
|
39
39
|
"build:clean": "del lib",
|
package/lib/client.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
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/config.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
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/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"data-model-designer.d.ts","sourceRoot":"","sources":["../../src/prompts/data-model-designer.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,yBAAyB,uprBAsmBmG,CAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/prompts/index.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,OAAO;;;;;;;;;;;;;CAenB,CAAA"}
|
package/lib/run.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":""}
|
|
@@ -1 +0,0 @@
|
|
|
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,CAgDtF"}
|
package/lib/tools/graph.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"graph.d.ts","sourceRoot":"","sources":["../../src/tools/graph.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAGhD,OAAO,EAAE,UAAU,EAAe,MAAM,uBAAuB,CAAA;AAG/D,KAAK,cAAc,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAA;AA0BnD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAsMpF"}
|
package/lib/tools/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
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"}
|