@kubun/mcp 0.9.0 → 0.11.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/lib/client.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { type SigningIdentity } from '@enkaku/token';
1
+ import { type SigningIdentity } from '@kokuin/token';
2
2
  import type { GraphsProvider } from '@kubun/protocol';
3
3
  export type ClientConfig = {
4
4
  type: 'memory';
package/lib/client.js CHANGED
@@ -1 +1,79 @@
1
- import{randomIdentity as t}from"@enkaku/token";import{KubunDB as e}from"@kubun/db";import{NodeSQLiteAdapter as r}from"@kubun/db-node-sqlite";import{PostgresAdapter as p}from"@kubun/db-postgres";import{KubunEngine as s}from"@kubun/engine";import{HTTPClient as o}from"@kubun/http-client";export function parseDatabase(t){return t.startsWith("http://")||t.startsWith("https://")?{type:"http",url:t}:t.startsWith("postgres://")?{type:"postgres",url:t}:":memory:"===t?{type:"memory"}:{type:"sqlite",path:t}}export async function createConnection(n){let i=n.identity??t(),a=function(t){switch(t.type){case"http":case"postgres":return t.url;case"sqlite":return t.path;case"memory":return":memory:"}}(n);if("http"===n.type)return{provider:new o({identity:i,serverID:n.serverID,url:n.url}),dispose:async()=>{},type:"http",address:a};let u=new e({adapter:"postgres"===n.type?new p({url:n.url}):new r({database:"sqlite"===n.type?n.path:":memory:"})}),m=new s({db:u,identity:i,plugins:[]});return{provider:m,dispose:async()=>{await m.dispose(),await u.close()},type:n.type,address:a}}
1
+ import { randomIdentity } from '@kokuin/token';
2
+ import { KubunDB } from '@kubun/db';
3
+ import { NodeSQLiteAdapter } from '@kubun/db-node-sqlite';
4
+ import { PostgresAdapter } from '@kubun/db-postgres';
5
+ import { KubunEngine } from '@kubun/engine';
6
+ import { HTTPClient } from '@kubun/http-client';
7
+ export function parseDatabase(database) {
8
+ if (database.startsWith('http://') || database.startsWith('https://')) {
9
+ return {
10
+ type: 'http',
11
+ url: database
12
+ };
13
+ }
14
+ if (database.startsWith('postgres://')) {
15
+ return {
16
+ type: 'postgres',
17
+ url: database
18
+ };
19
+ }
20
+ if (database === ':memory:') {
21
+ return {
22
+ type: 'memory'
23
+ };
24
+ }
25
+ return {
26
+ type: 'sqlite',
27
+ path: database
28
+ };
29
+ }
30
+ function getAddress(config) {
31
+ switch(config.type){
32
+ case 'http':
33
+ return config.url;
34
+ case 'postgres':
35
+ return config.url;
36
+ case 'sqlite':
37
+ return config.path;
38
+ case 'memory':
39
+ return ':memory:';
40
+ }
41
+ }
42
+ export async function createConnection(params) {
43
+ const identity = params.identity ?? randomIdentity();
44
+ const address = getAddress(params);
45
+ if (params.type === 'http') {
46
+ return {
47
+ provider: new HTTPClient({
48
+ identity,
49
+ serverID: params.serverID,
50
+ url: params.url
51
+ }),
52
+ dispose: async ()=>{},
53
+ type: 'http',
54
+ address
55
+ };
56
+ }
57
+ const adapter = params.type === 'postgres' ? new PostgresAdapter({
58
+ url: params.url
59
+ }) : new NodeSQLiteAdapter({
60
+ database: params.type === 'sqlite' ? params.path : ':memory:'
61
+ });
62
+ const db = new KubunDB({
63
+ adapter
64
+ });
65
+ const engine = new KubunEngine({
66
+ db,
67
+ identity,
68
+ plugins: []
69
+ });
70
+ return {
71
+ provider: engine,
72
+ dispose: async ()=>{
73
+ await engine.dispose();
74
+ await db.close();
75
+ },
76
+ type: params.type,
77
+ address
78
+ };
79
+ }
package/lib/config.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { SigningIdentity } from '@enkaku/token';
1
+ import type { SigningIdentity } from '@kokuin/token';
2
2
  import type { ServerConfig } from '@mokei/context-server';
3
3
  export type MCPConfig = {
4
4
  connect?: string;
package/lib/config.js CHANGED
@@ -1 +1,40 @@
1
- import{createConnection as t,parseDatabase as n}from"./client.js";import{prompts as o}from"./prompts/index.js";import{createClusterTools as e}from"./tools/cluster.js";import{createConnectionTools as i}from"./tools/connection.js";import{createGraphTools as r}from"./tools/graph.js";export async function createConfig(l={}){let s=null!=l.connect?{type:"http",url:l.connect,identity:l.identity}:null!=l.database?{...n(l.database),identity:l.identity}:null,a={current:null!=s?await t(s):null},c=i(a,l.identity),m=e(a),u=r(a);return{name:"kubun",version:"0.1.0",prompts:o,tools:{...c,...m,...u}}}
1
+ import { createConnection, parseDatabase } from './client.js';
2
+ import { prompts } from './prompts/index.js';
3
+ import { createClusterTools } from './tools/cluster.js';
4
+ import { createConnectionTools } from './tools/connection.js';
5
+ import { createGraphTools } from './tools/graph.js';
6
+ function parseConfig(config) {
7
+ if (config.connect != null) {
8
+ return {
9
+ type: 'http',
10
+ url: config.connect,
11
+ identity: config.identity
12
+ };
13
+ }
14
+ if (config.database != null) {
15
+ return {
16
+ ...parseDatabase(config.database),
17
+ identity: config.identity
18
+ };
19
+ }
20
+ return null;
21
+ }
22
+ export async function createConfig(config = {}) {
23
+ const params = parseConfig(config);
24
+ const container = {
25
+ current: params != null ? await createConnection(params) : null
26
+ };
27
+ const connectionTools = createConnectionTools(container, config.identity);
28
+ const clusterTools = createClusterTools(container);
29
+ const graphTools = createGraphTools(container);
30
+ return {
31
+ name: 'kubun',
32
+ version: '0.1.0',
33
+ prompts,
34
+ tools: {
35
+ ...connectionTools,
36
+ ...clusterTools,
37
+ ...graphTools
38
+ }
39
+ };
40
+ }
package/lib/container.js CHANGED
@@ -1 +1,14 @@
1
- export function getProvider(t){return t.current?.provider??null}export function notConnectedError(){return{isError:!0,content:[{type:"text",text:"No database connected. Use the connect tool first."}]}}
1
+ export function getProvider(container) {
2
+ return container.current?.provider ?? null;
3
+ }
4
+ export function notConnectedError() {
5
+ return {
6
+ isError: true,
7
+ content: [
8
+ {
9
+ type: 'text',
10
+ text: 'No database connected. Use the connect tool first.'
11
+ }
12
+ ]
13
+ };
14
+ }
package/lib/index.js CHANGED
@@ -1 +1,2 @@
1
- export{createConnection,parseDatabase}from"./client.js";export{createConfig}from"./config.js";
1
+ export { createConnection, parseDatabase } from './client.js';
2
+ export { createConfig } from './config.js';
@@ -1,4 +1,4 @@
1
- export const KUBUN_PROMPT_INSTRUCTIONS=`# Kubun Protocol Data Model Generator
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.`;
@@ -1 +1,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}}]})}};
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.js CHANGED
@@ -1,2 +1,19 @@
1
1
  #!/usr/bin/env node
2
- import{parseArgs as t}from"node:util";import{serveProcess as e}from"@mokei/context-server";import{createConfig as o}from"./config.js";let n=t({options:{connect:{type:"string"},db:{type:"string"}}});e(await o({connect:n.values.connect,database:n.values.db}));
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 = await createConfig({
16
+ connect: args.values.connect,
17
+ database: args.values.db
18
+ });
19
+ serveProcess(config);
@@ -1 +1,79 @@
1
- import{ClusterBuilder as e,clusterModel as t}from"@kubun/protocol";import{createTool as r}from"@mokei/context-server";import{getProvider as s,notConnectedError as o}from"../container.js";export function createClusterTools(n){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=s(n);if(null==t)return o();let r=await t.deployGraph({clusters:e.arguments.clusters,id:e.arguments.id,name:e.arguments.name});return{content:[{type:"text",text:`Clusters deployed to graph "${r.id}"`}],structuredContent:{id:r.id,record:r.record,aliases:r.aliases}}})}}
1
+ import { ClusterBuilder, clusterModel } from '@kubun/protocol';
2
+ import { createTool } from '@mokei/context-server';
3
+ import { getProvider, notConnectedError } from '../container.js';
4
+ export function createClusterTools(container) {
5
+ const create_cluster = createTool('Create a new cluster from model definitions', {
6
+ type: 'object',
7
+ properties: {
8
+ models: {
9
+ type: 'array',
10
+ items: {
11
+ type: 'object'
12
+ }
13
+ }
14
+ },
15
+ required: [
16
+ 'models'
17
+ ],
18
+ additionalProperties: false
19
+ }, async (ctx)=>{
20
+ const builder = new ClusterBuilder();
21
+ builder.addAll(ctx.arguments.models);
22
+ const cluster = builder.build();
23
+ return {
24
+ content: [
25
+ {
26
+ type: 'text',
27
+ text: 'Cluster created'
28
+ }
29
+ ],
30
+ structuredContent: {
31
+ cluster
32
+ }
33
+ };
34
+ });
35
+ const deploy_clusters = createTool('Deploy clusters to the Kubun backend', {
36
+ type: 'object',
37
+ properties: {
38
+ clusters: {
39
+ type: 'array',
40
+ items: clusterModel
41
+ },
42
+ id: {
43
+ type: 'string'
44
+ },
45
+ name: {
46
+ type: 'string'
47
+ }
48
+ },
49
+ required: [
50
+ 'clusters'
51
+ ],
52
+ additionalProperties: false
53
+ }, async (ctx)=>{
54
+ const provider = getProvider(container);
55
+ if (provider == null) return notConnectedError();
56
+ const result = await provider.deployGraph({
57
+ clusters: ctx.arguments.clusters,
58
+ id: ctx.arguments.id,
59
+ name: ctx.arguments.name
60
+ });
61
+ return {
62
+ content: [
63
+ {
64
+ type: 'text',
65
+ text: `Clusters deployed to graph "${result.id}"`
66
+ }
67
+ ],
68
+ structuredContent: {
69
+ id: result.id,
70
+ record: result.record,
71
+ aliases: result.aliases
72
+ }
73
+ };
74
+ });
75
+ return {
76
+ create_cluster,
77
+ deploy_clusters
78
+ };
79
+ }
@@ -1,4 +1,4 @@
1
- import type { SigningIdentity } from '@enkaku/token';
1
+ import type { SigningIdentity } from '@kokuin/token';
2
2
  import { createTool } from '@mokei/context-server';
3
3
  import type { ClientContainer } from '../container.js';
4
4
  type ToolDefinition = ReturnType<typeof createTool>;
@@ -1 +1,103 @@
1
- import{createTool as t}from"@mokei/context-server";import{createConnection as e,parseDatabase as n}from"../client.js";export function createConnectionTools(r,o){let c=t("Connect to a Kubun database. Accepts a SQLite file path, postgres:// URL, http(s):// URL, or :memory: for in-memory.",{type:"object",properties:{database:{type:"string",description:"SQLite file path, postgres:// URL, http(s):// URL, or :memory:"}},required:["database"],additionalProperties:!1},async t=>{null!=r.current&&await r.current.dispose();try{let c=n(t.arguments.database),a=await e({...c,identity:o});return r.current=a,{content:[{type:"text",text:`Connected to ${a.type} database: ${a.address}`}],structuredContent:{type:a.type,address:a.address}}}catch(t){return r.current=null,{isError:!0,content:[{type:"text",text:`Failed to connect: ${t instanceof Error?t.message:String(t)}`}]}}});return{connect:c,disconnect:t("Disconnect from the current Kubun database",{type:"object"},async()=>(null!=r.current&&(await r.current.dispose(),r.current=null),{content:[{type:"text",text:"Disconnected"}]})),connection_info:t("Get information about the current database connection",{type:"object"},async()=>null==r.current?{content:[{type:"text",text:"Not connected"}],structuredContent:{connected:!1}}:{content:[{type:"text",text:`Connected to ${r.current.type} database: ${r.current.address}`}],structuredContent:{connected:!0,type:r.current.type,address:r.current.address}})}}
1
+ import { createTool } from '@mokei/context-server';
2
+ import { createConnection, parseDatabase } from '../client.js';
3
+ export function createConnectionTools(container, identity) {
4
+ const connect = createTool('Connect to a Kubun database. Accepts a SQLite file path, postgres:// URL, http(s):// URL, or :memory: for in-memory.', {
5
+ type: 'object',
6
+ properties: {
7
+ database: {
8
+ type: 'string',
9
+ description: 'SQLite file path, postgres:// URL, http(s):// URL, or :memory:'
10
+ }
11
+ },
12
+ required: [
13
+ 'database'
14
+ ],
15
+ additionalProperties: false
16
+ }, async (ctx)=>{
17
+ if (container.current != null) {
18
+ await container.current.dispose();
19
+ }
20
+ try {
21
+ const config = parseDatabase(ctx.arguments.database);
22
+ const connection = await createConnection({
23
+ ...config,
24
+ identity
25
+ });
26
+ container.current = connection;
27
+ return {
28
+ content: [
29
+ {
30
+ type: 'text',
31
+ text: `Connected to ${connection.type} database: ${connection.address}`
32
+ }
33
+ ],
34
+ structuredContent: {
35
+ type: connection.type,
36
+ address: connection.address
37
+ }
38
+ };
39
+ } catch (error) {
40
+ container.current = null;
41
+ return {
42
+ isError: true,
43
+ content: [
44
+ {
45
+ type: 'text',
46
+ text: `Failed to connect: ${error instanceof Error ? error.message : String(error)}`
47
+ }
48
+ ]
49
+ };
50
+ }
51
+ });
52
+ const disconnect = createTool('Disconnect from the current Kubun database', {
53
+ type: 'object'
54
+ }, async ()=>{
55
+ if (container.current != null) {
56
+ await container.current.dispose();
57
+ container.current = null;
58
+ }
59
+ return {
60
+ content: [
61
+ {
62
+ type: 'text',
63
+ text: 'Disconnected'
64
+ }
65
+ ]
66
+ };
67
+ });
68
+ const connection_info = createTool('Get information about the current database connection', {
69
+ type: 'object'
70
+ }, async ()=>{
71
+ if (container.current == null) {
72
+ return {
73
+ content: [
74
+ {
75
+ type: 'text',
76
+ text: 'Not connected'
77
+ }
78
+ ],
79
+ structuredContent: {
80
+ connected: false
81
+ }
82
+ };
83
+ }
84
+ return {
85
+ content: [
86
+ {
87
+ type: 'text',
88
+ text: `Connected to ${container.current.type} database: ${container.current.address}`
89
+ }
90
+ ],
91
+ structuredContent: {
92
+ connected: true,
93
+ type: container.current.type,
94
+ address: container.current.address
95
+ }
96
+ };
97
+ });
98
+ return {
99
+ connect,
100
+ disconnect,
101
+ connection_info
102
+ };
103
+ }
@@ -1 +1,284 @@
1
- import{createSchema as e}from"@kubun/graphql";import{createTool as t}from"@mokei/context-server";import{printSchema as r}from"graphql";import{getProvider as n,notConnectedError as i}from"../container.js";export function createGraphTools(a){let o=t("List all available graphs",{type:"object"},async()=>{let e=n(a);if(null==e)return i();let t=await e.listGraphs(),r=t.graphs.map(e=>`${e.name} (${e.id})`).join(", ");return{content:[{type:"text",text:""===r?"No graphs available":`Available graphs: ${r}`}],structuredContent:{graphs:t.graphs}}}),s=t("Get information about a specific graph",{type:"object",properties:{id:{type:"string"}},required:["id"],additionalProperties:!1},async e=>{let t=n(a);if(null==t)return i();try{var r;let n,i=(n=(r=await t.loadGraph({id:e.arguments.id})).aliases??{},Object.entries(r.record).reduce((e,[t,r])=>(e[n[t]??r.name]={id:t,behavior:r.behavior,interfaces:r.interfaces,fields:Object.keys(r.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)}`}]}}}),u=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=>{let o=n(a);if(null==o)return i();try{let n=await o.loadGraph({id:t.arguments.id}),i=e({record:n.record,aliases:n.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(i)}]}}catch(e){return{isError:!0,content:[{type:"text",text:`Failed to get GraphQL schema: ${e instanceof Error?e.message:String(e)}`}]}}});return{graph_list:o,graph_info:s,graph_schema:u,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=>{let t=n(a);if(null==t)return i();try{let r=await t.queryGraph({id:e.arguments.id,text:e.arguments.query,variables:e.arguments.variables??{}});if(null!=r.errors&&r.errors.length>0)return{isError:!0,content:[{type:"text",text:r.errors.map(e=>e.toString()).join(", ")}],structuredContent:{errors:r.errors}};return{content:[{type:"text",text:JSON.stringify(r.data)}],structuredContent:{data:r.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=>{let t=n(a);if(null==t)return i();try{let r=await t.mutateGraph({id:e.arguments.id,text:e.arguments.query,variables:e.arguments.variables??{}});if(null!=r.errors&&r.errors.length>0)return{isError:!0,content:[{type:"text",text:r.errors.map(e=>e.toString()).join(", ")}],structuredContent:{errors:r.errors}};return{content:[{type:"text",text:JSON.stringify(r.data)}],structuredContent:{data:r.data}}}catch(e){return{isError:!0,content:[{type:"text",text:`Failed to execute GraphQL mutation: ${e instanceof Error?e.message:String(e)}`}]}}})}}
1
+ import { createSchema } from '@kubun/graphql';
2
+ import { createTool } from '@mokei/context-server';
3
+ import { printSchema } from 'graphql';
4
+ import { getProvider, notConnectedError } from '../container.js';
5
+ function getModelsInfo(result) {
6
+ const aliases = result.aliases ?? {};
7
+ return Object.entries(result.record).reduce((acc, [id, model])=>{
8
+ const alias = aliases[id] ?? model.name;
9
+ acc[alias] = {
10
+ id,
11
+ behavior: model.behavior,
12
+ interfaces: model.interfaces,
13
+ fields: Object.keys(model.schema.properties)
14
+ };
15
+ return acc;
16
+ }, {});
17
+ }
18
+ export function createGraphTools(container) {
19
+ const graph_list = createTool('List all available graphs', {
20
+ type: 'object'
21
+ }, async ()=>{
22
+ const provider = getProvider(container);
23
+ if (provider == null) return notConnectedError();
24
+ const result = await provider.listGraphs();
25
+ const graphs = result.graphs.map((graph)=>`${graph.name} (${graph.id})`).join(', ');
26
+ return {
27
+ content: [
28
+ {
29
+ type: 'text',
30
+ text: graphs === '' ? 'No graphs available' : `Available graphs: ${graphs}`
31
+ }
32
+ ],
33
+ structuredContent: {
34
+ graphs: result.graphs
35
+ }
36
+ };
37
+ });
38
+ const graph_info = createTool('Get information about a specific graph', {
39
+ type: 'object',
40
+ properties: {
41
+ id: {
42
+ type: 'string'
43
+ }
44
+ },
45
+ required: [
46
+ 'id'
47
+ ],
48
+ additionalProperties: false
49
+ }, async (ctx)=>{
50
+ const provider = getProvider(container);
51
+ if (provider == null) return notConnectedError();
52
+ try {
53
+ const result = await provider.loadGraph({
54
+ id: ctx.arguments.id
55
+ });
56
+ const info = getModelsInfo(result);
57
+ return {
58
+ content: [
59
+ {
60
+ type: 'text',
61
+ text: JSON.stringify(info)
62
+ }
63
+ ],
64
+ structuredContent: info
65
+ };
66
+ } catch (error) {
67
+ return {
68
+ isError: true,
69
+ content: [
70
+ {
71
+ type: 'text',
72
+ text: `Failed to get GraphQL schema: ${error instanceof Error ? error.message : String(error)}`
73
+ }
74
+ ]
75
+ };
76
+ }
77
+ });
78
+ const graph_schema = createTool('Get the GraphQL schema for the given graph ID. Supports selective generation to reduce schema size for LLM context.', {
79
+ type: 'object',
80
+ properties: {
81
+ id: {
82
+ type: 'string',
83
+ description: 'The graph ID'
84
+ },
85
+ onlyModels: {
86
+ type: 'array',
87
+ items: {
88
+ type: 'string'
89
+ },
90
+ description: 'Optional array of model IDs or aliases to include in schema. If not provided, all models are included.'
91
+ },
92
+ includeInterfaceDependencies: {
93
+ type: 'boolean',
94
+ description: 'Whether to include interface dependencies (default: true)'
95
+ },
96
+ includeRelationDependencies: {
97
+ type: 'boolean',
98
+ description: 'Whether to include relation dependencies (default: true)'
99
+ },
100
+ includeMutations: {
101
+ type: 'boolean',
102
+ description: 'Whether to include mutations in the schema (default: true)'
103
+ },
104
+ includeSubscriptions: {
105
+ type: 'boolean',
106
+ description: 'Whether to include subscriptions in the schema (default: true)'
107
+ }
108
+ },
109
+ required: [
110
+ 'id'
111
+ ],
112
+ additionalProperties: false
113
+ }, async (ctx)=>{
114
+ const provider = getProvider(container);
115
+ if (provider == null) return notConnectedError();
116
+ try {
117
+ const result = await provider.loadGraph({
118
+ id: ctx.arguments.id
119
+ });
120
+ const schema = createSchema({
121
+ record: result.record,
122
+ aliases: result.aliases,
123
+ onlyModels: ctx.arguments.onlyModels,
124
+ includeInterfaceDependencies: ctx.arguments.includeInterfaceDependencies,
125
+ includeRelationDependencies: ctx.arguments.includeRelationDependencies,
126
+ includeMutations: ctx.arguments.includeMutations,
127
+ includeSubscriptions: ctx.arguments.includeSubscriptions
128
+ });
129
+ return {
130
+ content: [
131
+ {
132
+ type: 'text',
133
+ text: printSchema(schema)
134
+ }
135
+ ]
136
+ };
137
+ } catch (error) {
138
+ return {
139
+ isError: true,
140
+ content: [
141
+ {
142
+ type: 'text',
143
+ text: `Failed to get GraphQL schema: ${error instanceof Error ? error.message : String(error)}`
144
+ }
145
+ ]
146
+ };
147
+ }
148
+ });
149
+ const graph_query = createTool('Execute a GraphQL query on the given graph ID', {
150
+ type: 'object',
151
+ properties: {
152
+ id: {
153
+ type: 'string'
154
+ },
155
+ query: {
156
+ type: 'string'
157
+ },
158
+ variables: {
159
+ type: 'object'
160
+ }
161
+ },
162
+ required: [
163
+ 'id',
164
+ 'query'
165
+ ],
166
+ additionalProperties: false
167
+ }, async (ctx)=>{
168
+ const provider = getProvider(container);
169
+ if (provider == null) return notConnectedError();
170
+ try {
171
+ const result = await provider.queryGraph({
172
+ id: ctx.arguments.id,
173
+ text: ctx.arguments.query,
174
+ variables: ctx.arguments.variables ?? {}
175
+ });
176
+ if (result.errors != null && result.errors.length > 0) {
177
+ return {
178
+ isError: true,
179
+ content: [
180
+ {
181
+ type: 'text',
182
+ text: result.errors.map((e)=>e.toString()).join(', ')
183
+ }
184
+ ],
185
+ structuredContent: {
186
+ errors: result.errors
187
+ }
188
+ };
189
+ }
190
+ return {
191
+ content: [
192
+ {
193
+ type: 'text',
194
+ text: JSON.stringify(result.data)
195
+ }
196
+ ],
197
+ structuredContent: {
198
+ data: result.data
199
+ }
200
+ };
201
+ } catch (error) {
202
+ return {
203
+ isError: true,
204
+ content: [
205
+ {
206
+ type: 'text',
207
+ text: `Failed to execute GraphQL query: ${error instanceof Error ? error.message : String(error)}`
208
+ }
209
+ ]
210
+ };
211
+ }
212
+ });
213
+ const graph_mutate = createTool('Execute a GraphQL mutation on the given graph ID', {
214
+ type: 'object',
215
+ properties: {
216
+ id: {
217
+ type: 'string'
218
+ },
219
+ query: {
220
+ type: 'string'
221
+ },
222
+ variables: {
223
+ type: 'object'
224
+ }
225
+ },
226
+ required: [
227
+ 'id',
228
+ 'query'
229
+ ],
230
+ additionalProperties: false
231
+ }, async (ctx)=>{
232
+ const provider = getProvider(container);
233
+ if (provider == null) return notConnectedError();
234
+ try {
235
+ const result = await provider.mutateGraph({
236
+ id: ctx.arguments.id,
237
+ text: ctx.arguments.query,
238
+ variables: ctx.arguments.variables ?? {}
239
+ });
240
+ if (result.errors != null && result.errors.length > 0) {
241
+ return {
242
+ isError: true,
243
+ content: [
244
+ {
245
+ type: 'text',
246
+ text: result.errors.map((e)=>e.toString()).join(', ')
247
+ }
248
+ ],
249
+ structuredContent: {
250
+ errors: result.errors
251
+ }
252
+ };
253
+ }
254
+ return {
255
+ content: [
256
+ {
257
+ type: 'text',
258
+ text: JSON.stringify(result.data)
259
+ }
260
+ ],
261
+ structuredContent: {
262
+ data: result.data
263
+ }
264
+ };
265
+ } catch (error) {
266
+ return {
267
+ isError: true,
268
+ content: [
269
+ {
270
+ type: 'text',
271
+ text: `Failed to execute GraphQL mutation: ${error instanceof Error ? error.message : String(error)}`
272
+ }
273
+ ]
274
+ };
275
+ }
276
+ });
277
+ return {
278
+ graph_list,
279
+ graph_info,
280
+ graph_schema,
281
+ graph_query,
282
+ graph_mutate
283
+ };
284
+ }
@@ -1 +1,3 @@
1
- export{createClusterTools}from"./cluster.js";export{createConnectionTools}from"./connection.js";export{createGraphTools}from"./graph.js";
1
+ export { createClusterTools } from './cluster.js';
2
+ export { createConnectionTools } from './connection.js';
3
+ export { createGraphTools } from './graph.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kubun/mcp",
3
- "version": "0.9.0",
3
+ "version": "0.11.0",
4
4
  "license": "see LICENSE.md",
5
5
  "keywords": [],
6
6
  "type": "module",
@@ -18,25 +18,25 @@
18
18
  ],
19
19
  "sideEffects": false,
20
20
  "dependencies": {
21
- "@enkaku/token": "^0.15.0",
22
- "@mokei/context-server": "^0.6.0",
23
- "graphql": "^16.13.2",
24
- "@kubun/db": "^0.9.0",
25
- "@kubun/db-postgres": "^0.9.0",
26
- "@kubun/engine": "^0.9.0",
27
- "@kubun/db-node-sqlite": "^0.9.0",
28
- "@kubun/graphql": "^0.9.0",
29
- "@kubun/protocol": "^0.9.0",
30
- "@kubun/http-client": "^0.9.0"
21
+ "@kokuin/token": "^0.1.1",
22
+ "@mokei/context-server": "^0.8.0",
23
+ "graphql": "^16.14.2",
24
+ "@kubun/db": "^0.11.0",
25
+ "@kubun/db-postgres": "^0.11.0",
26
+ "@kubun/db-node-sqlite": "^0.11.0",
27
+ "@kubun/engine": "^0.11.0",
28
+ "@kubun/http-client": "^0.11.0",
29
+ "@kubun/protocol": "^0.11.0",
30
+ "@kubun/graphql": "^0.11.0"
31
31
  },
32
32
  "devDependencies": {
33
- "@enkaku/transport": "^0.15.0",
34
- "@mokei/context-client": "^0.6.0",
35
- "@mokei/context-protocol": "^0.6.0"
33
+ "@enkaku/transport": "^0.18.1",
34
+ "@mokei/context-client": "^0.8.0",
35
+ "@mokei/context-protocol": "^0.8.0"
36
36
  },
37
37
  "scripts": {
38
38
  "build:clean": "del lib",
39
- "build:js": "swc src -d ./lib --config-file ../../swc.json --strip-leading-paths",
39
+ "build:js": "swc src -d ./lib --config-file ../../node_modules/@kigu/dev/swc.json --strip-leading-paths",
40
40
  "build:types": "tsc --emitDeclarationOnly --skipLibCheck",
41
41
  "build": "pnpm run build:clean && pnpm run build:js && pnpm run build:types",
42
42
  "test:types": "tsc --noEmit -p tsconfig.test.json",