@livestore/cli 0.0.0-snapshot-2ac5fd340c97c9e07fe4c5dc6d31d5132aa6557c.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/.claude/settings.local.json +12 -0
- package/LICENSE +201 -0
- package/dist/cli +0 -0
- package/dist/cli.d.ts +15 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +22 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/mcp-coach.d.ts +15 -0
- package/dist/commands/mcp-coach.d.ts.map +1 -0
- package/dist/commands/mcp-coach.js +87 -0
- package/dist/commands/mcp-coach.js.map +1 -0
- package/dist/commands/mcp-tools.d.ts +41 -0
- package/dist/commands/mcp-tools.d.ts.map +1 -0
- package/dist/commands/mcp-tools.js +148 -0
- package/dist/commands/mcp-tools.js.map +1 -0
- package/dist/commands/mcp.d.ts +5 -0
- package/dist/commands/mcp.d.ts.map +1 -0
- package/dist/commands/mcp.js +67 -0
- package/dist/commands/mcp.js.map +1 -0
- package/dist/commands/new-project.d.ts +34 -0
- package/dist/commands/new-project.d.ts.map +1 -0
- package/dist/commands/new-project.js +163 -0
- package/dist/commands/new-project.js.map +1 -0
- package/dist/mcp-content/architecture.d.ts +2 -0
- package/dist/mcp-content/architecture.d.ts.map +1 -0
- package/dist/mcp-content/architecture.js +171 -0
- package/dist/mcp-content/architecture.js.map +1 -0
- package/dist/mcp-content/features.d.ts +2 -0
- package/dist/mcp-content/features.d.ts.map +1 -0
- package/dist/mcp-content/features.js +177 -0
- package/dist/mcp-content/features.js.map +1 -0
- package/dist/mcp-content/getting-started.d.ts +2 -0
- package/dist/mcp-content/getting-started.d.ts.map +1 -0
- package/dist/mcp-content/getting-started.js +405 -0
- package/dist/mcp-content/getting-started.js.map +1 -0
- package/dist/mcp-content/overview.d.ts +2 -0
- package/dist/mcp-content/overview.d.ts.map +1 -0
- package/dist/mcp-content/overview.js +120 -0
- package/dist/mcp-content/overview.js.map +1 -0
- package/dist/mcp-content/schemas/blog.d.ts +2 -0
- package/dist/mcp-content/schemas/blog.d.ts.map +1 -0
- package/dist/mcp-content/schemas/blog.js +223 -0
- package/dist/mcp-content/schemas/blog.js.map +1 -0
- package/dist/mcp-content/schemas/ecommerce.d.ts +2 -0
- package/dist/mcp-content/schemas/ecommerce.d.ts.map +1 -0
- package/dist/mcp-content/schemas/ecommerce.js +436 -0
- package/dist/mcp-content/schemas/ecommerce.js.map +1 -0
- package/dist/mcp-content/schemas/social.d.ts +2 -0
- package/dist/mcp-content/schemas/social.d.ts.map +1 -0
- package/dist/mcp-content/schemas/social.js +339 -0
- package/dist/mcp-content/schemas/social.js.map +1 -0
- package/dist/mcp-content/schemas/todo.d.ts +2 -0
- package/dist/mcp-content/schemas/todo.d.ts.map +1 -0
- package/dist/mcp-content/schemas/todo.js +172 -0
- package/dist/mcp-content/schemas/todo.js.map +1 -0
- package/dist/mod.d.ts +2 -0
- package/dist/mod.d.ts.map +1 -0
- package/dist/mod.js +2 -0
- package/dist/mod.js.map +1 -0
- package/dist/test-tool.d.ts +2 -0
- package/dist/test-tool.d.ts.map +1 -0
- package/dist/test-tool.js +57 -0
- package/dist/test-tool.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +27 -0
- package/src/cli.ts +35 -0
- package/src/commands/mcp-coach.ts +121 -0
- package/src/commands/mcp-tools.ts +169 -0
- package/src/commands/mcp.ts +97 -0
- package/src/commands/new-project.ts +263 -0
- package/src/mcp-content/architecture.ts +170 -0
- package/src/mcp-content/features.ts +176 -0
- package/src/mcp-content/getting-started.ts +404 -0
- package/src/mcp-content/overview.ts +119 -0
- package/src/mcp-content/schemas/blog.ts +222 -0
- package/src/mcp-content/schemas/ecommerce.ts +435 -0
- package/src/mcp-content/schemas/social.ts +338 -0
- package/src/mcp-content/schemas/todo.ts +171 -0
- package/src/mod.ts +1 -0
- package/tsconfig.json +9 -0
package/package.json
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
{
|
2
|
+
"name": "@livestore/cli",
|
3
|
+
"version": "0.0.0-snapshot-2ac5fd340c97c9e07fe4c5dc6d31d5132aa6557c.0",
|
4
|
+
"type": "module",
|
5
|
+
"exports": {
|
6
|
+
".": "./dist/mod.js"
|
7
|
+
},
|
8
|
+
"bin": {
|
9
|
+
"livestore": "./dist/cli.js"
|
10
|
+
},
|
11
|
+
"publishConfig": {
|
12
|
+
"access": "public"
|
13
|
+
},
|
14
|
+
"dependencies": {
|
15
|
+
"@effect/ai-openai": "^0.29.0",
|
16
|
+
"@livestore/utils-dev": "0.0.0-snapshot-2ac5fd340c97c9e07fe4c5dc6d31d5132aa6557c.0",
|
17
|
+
"@livestore/utils": "0.0.0-snapshot-2ac5fd340c97c9e07fe4c5dc6d31d5132aa6557c.0"
|
18
|
+
},
|
19
|
+
"devDependencies": {
|
20
|
+
"@types/node": "24.2.0",
|
21
|
+
"typescript": "^5.9.2"
|
22
|
+
},
|
23
|
+
"scripts": {
|
24
|
+
"build": "tsc",
|
25
|
+
"dev": "bun src/cli.ts"
|
26
|
+
}
|
27
|
+
}
|
package/src/cli.ts
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
#!/usr/bin/env node
|
2
|
+
|
3
|
+
import { Effect, FetchHttpClient, Layer, Logger, LogLevel } from '@livestore/utils/effect'
|
4
|
+
import { Cli, PlatformNode } from '@livestore/utils/node'
|
5
|
+
import { mcpCommand } from './commands/mcp.ts'
|
6
|
+
import { newProjectCommand } from './commands/new-project.ts'
|
7
|
+
|
8
|
+
const helloCommand = Cli.Command.make(
|
9
|
+
'hello',
|
10
|
+
{
|
11
|
+
name: Cli.Options.text('name').pipe(Cli.Options.withDefault('World')),
|
12
|
+
},
|
13
|
+
Effect.fn(function* ({ name }: { name: string }) {
|
14
|
+
yield* Effect.log(`Hello, ${name}! 🎉`)
|
15
|
+
}),
|
16
|
+
)
|
17
|
+
|
18
|
+
export const command = Cli.Command.make('livestore', {
|
19
|
+
verbose: Cli.Options.boolean('verbose').pipe(Cli.Options.withDefault(false)),
|
20
|
+
}).pipe(Cli.Command.withSubcommands([helloCommand, mcpCommand, newProjectCommand]))
|
21
|
+
|
22
|
+
if (import.meta.main) {
|
23
|
+
const cli = Cli.Command.run(command, {
|
24
|
+
name: 'livestore',
|
25
|
+
version: '0.1.0',
|
26
|
+
})
|
27
|
+
|
28
|
+
const layer = Layer.mergeAll(
|
29
|
+
PlatformNode.NodeContext.layer,
|
30
|
+
FetchHttpClient.layer,
|
31
|
+
Logger.minimumLogLevel(LogLevel.Info),
|
32
|
+
)
|
33
|
+
|
34
|
+
cli(process.argv).pipe(Effect.provide(layer), PlatformNode.NodeRuntime.runMain)
|
35
|
+
}
|
@@ -0,0 +1,121 @@
|
|
1
|
+
import { OpenAiClient, OpenAiLanguageModel } from '@effect/ai-openai'
|
2
|
+
import {
|
3
|
+
AiError,
|
4
|
+
AiLanguageModel,
|
5
|
+
AiTool,
|
6
|
+
Config,
|
7
|
+
Effect,
|
8
|
+
FetchHttpClient,
|
9
|
+
Layer,
|
10
|
+
Schema,
|
11
|
+
} from '@livestore/utils/effect'
|
12
|
+
|
13
|
+
// Define the coach tool that analyzes LiveStore usage
|
14
|
+
export const coachTool = AiTool.make('livestore_coach', {
|
15
|
+
description:
|
16
|
+
'Analyze LiveStore code (schemas, queries, mutations, etc.) and provide AI-powered feedback on best practices, performance, and improvements.',
|
17
|
+
parameters: {
|
18
|
+
code: Schema.String.annotations({
|
19
|
+
description: 'The LiveStore code to analyze (TypeScript/JavaScript)',
|
20
|
+
}),
|
21
|
+
codeType: Schema.optional(
|
22
|
+
Schema.String.annotations({
|
23
|
+
description: "Type of code being analyzed: 'schema', 'query', 'mutation', 'component', or 'general'",
|
24
|
+
}),
|
25
|
+
),
|
26
|
+
},
|
27
|
+
success: Schema.Struct({
|
28
|
+
feedback: Schema.String.annotations({
|
29
|
+
description: 'AI-generated feedback and recommendations for the code',
|
30
|
+
}),
|
31
|
+
score: Schema.optional(
|
32
|
+
Schema.Number.annotations({
|
33
|
+
description: 'Code quality score from 1-10 (optional)',
|
34
|
+
}),
|
35
|
+
),
|
36
|
+
suggestions: Schema.Array(
|
37
|
+
Schema.String.annotations({
|
38
|
+
description: 'Specific actionable suggestions for improvement',
|
39
|
+
}),
|
40
|
+
).annotations({
|
41
|
+
description: 'List of specific improvement suggestions',
|
42
|
+
}),
|
43
|
+
}),
|
44
|
+
failure: AiError.AiError,
|
45
|
+
})
|
46
|
+
|
47
|
+
const OpenAiClientLayer = OpenAiClient.layerConfig({
|
48
|
+
apiKey: Config.redacted('OPENAI_API_KEY'),
|
49
|
+
})
|
50
|
+
|
51
|
+
const OpenAiModel = OpenAiLanguageModel.layer({
|
52
|
+
model: 'gpt-5-nano',
|
53
|
+
})
|
54
|
+
|
55
|
+
// Coach tool handler that uses OpenAI for analysis
|
56
|
+
export const coachToolHandler = Effect.fnUntraced(
|
57
|
+
function* ({ code, codeType }) {
|
58
|
+
// Build the analysis prompt
|
59
|
+
const codeTypeContext = codeType ? `This is ${codeType} code using LiveStore. ` : 'This is LiveStore code. '
|
60
|
+
|
61
|
+
const prompt = `${codeTypeContext}Please review the following code and provide helpful feedback focusing on:
|
62
|
+
|
63
|
+
1. LiveStore best practices and conventions
|
64
|
+
2. Schema design and relationships (if applicable)
|
65
|
+
3. Query optimization and performance
|
66
|
+
4. Code structure and maintainability
|
67
|
+
5. Security considerations
|
68
|
+
6. Naming conventions
|
69
|
+
7. TypeScript usage and type safety
|
70
|
+
|
71
|
+
Code to review:
|
72
|
+
\`\`\`typescript
|
73
|
+
${code}
|
74
|
+
\`\`\`
|
75
|
+
|
76
|
+
Please provide:
|
77
|
+
1. Overall assessment and quality score (1-10)
|
78
|
+
2. Specific areas for improvement
|
79
|
+
3. Best practice recommendations
|
80
|
+
4. Any potential issues or concerns
|
81
|
+
|
82
|
+
Format your response as constructive feedback that helps developers improve their LiveStore usage.`
|
83
|
+
|
84
|
+
const systemPrompt = `You are an expert LiveStore developer and code reviewer. Provide constructive, specific, and actionable feedback on LiveStore code. Focus on best practices, performance, and maintainability.`
|
85
|
+
|
86
|
+
// Get OpenAI client and call the API
|
87
|
+
const llm = yield* AiLanguageModel.AiLanguageModel
|
88
|
+
const completion = yield* llm.generateText({ prompt, system: systemPrompt })
|
89
|
+
|
90
|
+
const feedback = completion.text ?? 'Unable to generate feedback'
|
91
|
+
|
92
|
+
// Extract suggestions from the feedback (simple approach)
|
93
|
+
const suggestions: string[] = feedback
|
94
|
+
.split('\n')
|
95
|
+
.filter(
|
96
|
+
(line: string) =>
|
97
|
+
line.trim().startsWith('-') ||
|
98
|
+
line.trim().startsWith('*') ||
|
99
|
+
line.trim().startsWith('•') ||
|
100
|
+
line.toLowerCase().includes('recommend') ||
|
101
|
+
line.toLowerCase().includes('consider') ||
|
102
|
+
line.toLowerCase().includes('improve'),
|
103
|
+
)
|
104
|
+
.map((line: string) => line.replace(/^[-*•]\s*/, '').trim())
|
105
|
+
.filter((suggestion: string) => suggestion.length > 10)
|
106
|
+
.slice(0, 5) // Limit to 5 suggestions
|
107
|
+
|
108
|
+
// Try to extract a score (simple regex approach)
|
109
|
+
const scoreMatch = feedback.match(/(?:score|rating|quality).*?(\d+(?:\.\d+)?)/i)
|
110
|
+
const score = scoreMatch ? Number.parseFloat(scoreMatch[1] ?? '0') : undefined
|
111
|
+
|
112
|
+
return {
|
113
|
+
feedback,
|
114
|
+
score: score && score >= 1 && score <= 10 ? score : undefined,
|
115
|
+
suggestions,
|
116
|
+
}
|
117
|
+
},
|
118
|
+
Effect.provide(Layer.provideMerge(OpenAiModel, OpenAiClientLayer)),
|
119
|
+
Effect.provide(FetchHttpClient.layer),
|
120
|
+
Effect.catchTag('ConfigError', (e) => Effect.die(e)),
|
121
|
+
)
|
@@ -0,0 +1,169 @@
|
|
1
|
+
import { AiTool, AiToolkit, Effect, Schema } from '@livestore/utils/effect'
|
2
|
+
import { blogSchemaContent } from '../mcp-content/schemas/blog.ts'
|
3
|
+
import { ecommerceSchemaContent } from '../mcp-content/schemas/ecommerce.ts'
|
4
|
+
import { socialSchemaContent } from '../mcp-content/schemas/social.ts'
|
5
|
+
import { todoSchemaContent } from '../mcp-content/schemas/todo.ts'
|
6
|
+
import { coachTool, coachToolHandler } from './mcp-coach.ts'
|
7
|
+
|
8
|
+
// Create toolkit with tools and handlers following Tim Smart's pattern
|
9
|
+
export const livestoreToolkit = AiToolkit.make(
|
10
|
+
coachTool,
|
11
|
+
|
12
|
+
AiTool.make('livestore_generate_schema', {
|
13
|
+
description:
|
14
|
+
'Generate a LiveStore schema for a specific use case. Choose from predefined types (todo, blog, social, ecommerce) or request a custom schema by providing a description.',
|
15
|
+
parameters: {
|
16
|
+
schemaType: Schema.String.annotations({
|
17
|
+
description: "Schema type: 'todo', 'blog', 'social', 'ecommerce', or 'custom'",
|
18
|
+
}),
|
19
|
+
customDescription: Schema.optional(
|
20
|
+
Schema.String.annotations({
|
21
|
+
description:
|
22
|
+
"For custom schemas: describe your data model needs (e.g., 'user management system with roles and permissions')",
|
23
|
+
}),
|
24
|
+
),
|
25
|
+
},
|
26
|
+
success: Schema.Struct({
|
27
|
+
schemaCode: Schema.String.annotations({
|
28
|
+
description: 'The generated LiveStore schema TypeScript code',
|
29
|
+
}),
|
30
|
+
explanation: Schema.String.annotations({
|
31
|
+
description: 'Brief explanation of the schema structure',
|
32
|
+
}),
|
33
|
+
}),
|
34
|
+
}),
|
35
|
+
|
36
|
+
AiTool.make('livestore_get_example_schema', {
|
37
|
+
description:
|
38
|
+
'Get a complete example LiveStore schema with TypeScript code. Returns ready-to-use schema definitions for common application types.',
|
39
|
+
parameters: {
|
40
|
+
type: Schema.String.annotations({
|
41
|
+
description: "Example type: 'todo', 'blog', 'social', or 'ecommerce'",
|
42
|
+
}),
|
43
|
+
},
|
44
|
+
success: Schema.Struct({
|
45
|
+
schemaCode: Schema.String.annotations({
|
46
|
+
description: 'The complete LiveStore schema code',
|
47
|
+
}),
|
48
|
+
description: Schema.String.annotations({
|
49
|
+
description: 'Description of what this schema models',
|
50
|
+
}),
|
51
|
+
}),
|
52
|
+
})
|
53
|
+
.annotate(AiTool.Readonly, true)
|
54
|
+
.annotate(AiTool.Destructive, false),
|
55
|
+
)
|
56
|
+
|
57
|
+
// Tool handlers using Tim Smart's pattern
|
58
|
+
export const toolHandlers = livestoreToolkit.of({
|
59
|
+
livestore_coach: coachToolHandler,
|
60
|
+
|
61
|
+
livestore_generate_schema: Effect.fnUntraced(function* ({ schemaType, customDescription }) {
|
62
|
+
let schemaCode: string
|
63
|
+
let explanation: string
|
64
|
+
|
65
|
+
switch (schemaType.toLowerCase()) {
|
66
|
+
case 'todo':
|
67
|
+
schemaCode = todoSchemaContent
|
68
|
+
explanation = 'Todo application schema with tasks, tags, and many-to-many relationships'
|
69
|
+
break
|
70
|
+
case 'blog':
|
71
|
+
schemaCode = blogSchemaContent
|
72
|
+
explanation = 'Blog platform schema with posts, comments, and publishing workflow'
|
73
|
+
break
|
74
|
+
case 'social':
|
75
|
+
schemaCode = socialSchemaContent
|
76
|
+
explanation = 'Social media schema with users, posts, follows, and likes'
|
77
|
+
break
|
78
|
+
case 'ecommerce':
|
79
|
+
schemaCode = ecommerceSchemaContent
|
80
|
+
explanation = 'E-commerce schema with products, categories, orders, and inventory'
|
81
|
+
break
|
82
|
+
case 'custom': {
|
83
|
+
if (!customDescription) {
|
84
|
+
schemaCode = `// Custom schema requested but no description provided
|
85
|
+
import { Schema } from '@livestore/livestore'
|
86
|
+
|
87
|
+
// Please provide a description of your data model needs
|
88
|
+
export const CustomSchema = Schema.table('items', {
|
89
|
+
id: Schema.id,
|
90
|
+
name: Schema.text,
|
91
|
+
createdAt: Schema.datetime.default('now')
|
92
|
+
})
|
93
|
+
|
94
|
+
export const schema = Schema.create({
|
95
|
+
items: CustomSchema
|
96
|
+
})`
|
97
|
+
explanation = 'Basic custom schema template - please provide more details about your requirements'
|
98
|
+
break
|
99
|
+
}
|
100
|
+
|
101
|
+
// Generate a basic custom schema based on description
|
102
|
+
const tableName = customDescription.toLowerCase().includes('user')
|
103
|
+
? 'users'
|
104
|
+
: customDescription.toLowerCase().includes('product')
|
105
|
+
? 'products'
|
106
|
+
: customDescription.toLowerCase().includes('post')
|
107
|
+
? 'posts'
|
108
|
+
: 'items'
|
109
|
+
|
110
|
+
schemaCode = `// Custom schema based on: ${customDescription}
|
111
|
+
import { Schema } from '@livestore/livestore'
|
112
|
+
|
113
|
+
export const ${tableName.charAt(0).toUpperCase() + tableName.slice(0, -1)}Schema = Schema.table('${tableName}', {
|
114
|
+
id: Schema.id,
|
115
|
+
name: Schema.text,
|
116
|
+
description: Schema.text.optional(),
|
117
|
+
createdAt: Schema.datetime.default('now'),
|
118
|
+
updatedAt: Schema.datetime.default('now')
|
119
|
+
})
|
120
|
+
|
121
|
+
export const schema = Schema.create({
|
122
|
+
${tableName}: ${tableName.charAt(0).toUpperCase() + tableName.slice(0, -1)}Schema
|
123
|
+
})`
|
124
|
+
|
125
|
+
explanation = `Custom schema generated for: ${customDescription}. This is a basic template - you may need to customize the fields based on your specific requirements.`
|
126
|
+
break
|
127
|
+
}
|
128
|
+
default:
|
129
|
+
schemaCode = todoSchemaContent
|
130
|
+
explanation =
|
131
|
+
'Unknown schema type, returning todo example. Available types: todo, blog, social, ecommerce, custom'
|
132
|
+
}
|
133
|
+
|
134
|
+
return { schemaCode, explanation }
|
135
|
+
}),
|
136
|
+
|
137
|
+
livestore_get_example_schema: Effect.fnUntraced(function* ({ type }) {
|
138
|
+
let schemaCode: string
|
139
|
+
let description: string
|
140
|
+
|
141
|
+
switch (type.toLowerCase()) {
|
142
|
+
case 'todo':
|
143
|
+
schemaCode = todoSchemaContent
|
144
|
+
description =
|
145
|
+
'Complete todo application with tasks, tags, and many-to-many relationships. Includes boolean completion status and timestamps.'
|
146
|
+
break
|
147
|
+
case 'blog':
|
148
|
+
schemaCode = blogSchemaContent
|
149
|
+
description =
|
150
|
+
'Blog platform with posts and comments. Features published status, unique slugs, and author attribution.'
|
151
|
+
break
|
152
|
+
case 'social':
|
153
|
+
schemaCode = socialSchemaContent
|
154
|
+
description =
|
155
|
+
'Social media platform with users, posts, follows, and likes. Includes user profiles and social interactions.'
|
156
|
+
break
|
157
|
+
case 'ecommerce':
|
158
|
+
schemaCode = ecommerceSchemaContent
|
159
|
+
description =
|
160
|
+
'E-commerce platform with products, categories, orders, and inventory management. Features order items and status tracking.'
|
161
|
+
break
|
162
|
+
default:
|
163
|
+
schemaCode = todoSchemaContent
|
164
|
+
description = 'Default todo example (unknown type requested). Available types: todo, blog, social, ecommerce'
|
165
|
+
}
|
166
|
+
|
167
|
+
return { schemaCode, description }
|
168
|
+
}),
|
169
|
+
})
|
@@ -0,0 +1,97 @@
|
|
1
|
+
import { Effect, Layer, Logger, McpServer } from '@livestore/utils/effect'
|
2
|
+
import { Cli, PlatformNode } from '@livestore/utils/node'
|
3
|
+
import { architectureContent } from '../mcp-content/architecture.ts'
|
4
|
+
import { featuresContent } from '../mcp-content/features.ts'
|
5
|
+
import { gettingStartedContent } from '../mcp-content/getting-started.ts'
|
6
|
+
// Content imports
|
7
|
+
import { overviewContent } from '../mcp-content/overview.ts'
|
8
|
+
import { blogSchemaContent } from '../mcp-content/schemas/blog.ts'
|
9
|
+
import { ecommerceSchemaContent } from '../mcp-content/schemas/ecommerce.ts'
|
10
|
+
import { socialSchemaContent } from '../mcp-content/schemas/social.ts'
|
11
|
+
import { todoSchemaContent } from '../mcp-content/schemas/todo.ts'
|
12
|
+
|
13
|
+
// Tools imports
|
14
|
+
import { livestoreToolkit, toolHandlers } from './mcp-tools.ts'
|
15
|
+
|
16
|
+
const LivestoreResources = Layer.mergeAll(
|
17
|
+
McpServer.resource({
|
18
|
+
uri: 'livestore://overview',
|
19
|
+
name: 'LiveStore Overview',
|
20
|
+
description: 'Overview of LiveStore - the local-first data platform',
|
21
|
+
content: Effect.succeed(overviewContent),
|
22
|
+
}),
|
23
|
+
|
24
|
+
McpServer.resource({
|
25
|
+
uri: 'livestore://features',
|
26
|
+
name: 'LiveStore Features',
|
27
|
+
description: 'Core features and capabilities of LiveStore',
|
28
|
+
content: Effect.succeed(featuresContent),
|
29
|
+
}),
|
30
|
+
|
31
|
+
McpServer.resource({
|
32
|
+
uri: 'livestore://getting-started',
|
33
|
+
name: 'Getting Started with LiveStore',
|
34
|
+
description: 'Quick start guide for LiveStore development',
|
35
|
+
content: Effect.succeed(gettingStartedContent),
|
36
|
+
}),
|
37
|
+
|
38
|
+
McpServer.resource({
|
39
|
+
uri: 'livestore://architecture',
|
40
|
+
name: 'LiveStore Architecture',
|
41
|
+
description: 'Technical architecture and design principles of LiveStore',
|
42
|
+
content: Effect.succeed(architectureContent),
|
43
|
+
}),
|
44
|
+
|
45
|
+
McpServer.resource({
|
46
|
+
uri: 'livestore://schemas/todo',
|
47
|
+
name: 'Todo App Schema',
|
48
|
+
description: 'Complete LiveStore schema for a todo application with tags',
|
49
|
+
content: Effect.succeed(todoSchemaContent),
|
50
|
+
}),
|
51
|
+
|
52
|
+
McpServer.resource({
|
53
|
+
uri: 'livestore://schemas/blog',
|
54
|
+
name: 'Blog Platform Schema',
|
55
|
+
description: 'LiveStore schema for a blog platform with posts and comments',
|
56
|
+
content: Effect.succeed(blogSchemaContent),
|
57
|
+
}),
|
58
|
+
|
59
|
+
McpServer.resource({
|
60
|
+
uri: 'livestore://schemas/social',
|
61
|
+
name: 'Social Media Schema',
|
62
|
+
description: 'LiveStore schema for a social media platform with users, posts, and interactions',
|
63
|
+
content: Effect.succeed(socialSchemaContent),
|
64
|
+
}),
|
65
|
+
|
66
|
+
McpServer.resource({
|
67
|
+
uri: 'livestore://schemas/ecommerce',
|
68
|
+
name: 'E-commerce Schema',
|
69
|
+
description: 'LiveStore schema for an e-commerce platform with products, orders, and categories',
|
70
|
+
content: Effect.succeed(ecommerceSchemaContent),
|
71
|
+
}),
|
72
|
+
)
|
73
|
+
|
74
|
+
const LivestoreTools = McpServer.toolkit(livestoreToolkit).pipe(Layer.provide(livestoreToolkit.toLayer(toolHandlers)))
|
75
|
+
|
76
|
+
const mcpServerCommand = Cli.Command.make(
|
77
|
+
'server',
|
78
|
+
{},
|
79
|
+
Effect.fn(function* () {
|
80
|
+
yield* Effect.log('🚀 Starting LiveStore MCP Server...')
|
81
|
+
|
82
|
+
// Following Tim Smart's exact pattern from main.ts
|
83
|
+
return yield* McpServer.layerStdio({
|
84
|
+
name: 'livestore-mcp',
|
85
|
+
version: '0.1.0',
|
86
|
+
stdin: PlatformNode.NodeStream.stdin,
|
87
|
+
stdout: PlatformNode.NodeSink.stdout,
|
88
|
+
}).pipe(
|
89
|
+
Layer.provide(LivestoreResources),
|
90
|
+
Layer.provide(LivestoreTools),
|
91
|
+
Layer.provide(Logger.add(Logger.prettyLogger({ stderr: true }))),
|
92
|
+
Layer.launch,
|
93
|
+
)
|
94
|
+
}),
|
95
|
+
)
|
96
|
+
|
97
|
+
export const mcpCommand = Cli.Command.make('mcp').pipe(Cli.Command.withSubcommands([mcpServerCommand]))
|