@objectstack/mcp 8.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,93 @@
1
+ License text copyright (c) 2020 MariaDB Corporation Ab, All Rights Reserved.
2
+ "Business Source License" is a trademark of MariaDB Corporation Ab.
3
+
4
+ Parameters
5
+
6
+ Licensor: ObjectStack AI LLC
7
+ Licensed Work: ObjectStack Runtime: the BSL-licensed packages
8
+ of the ObjectStack monorepo as listed in LICENSING.md.
9
+ Copyright (c) 2026 ObjectStack AI LLC.
10
+ Additional Use Grant: You may make production use of the Licensed Work, provided
11
+ Your use does not include offering the Licensed Work to third
12
+ parties on a hosted or embedded basis in order to compete with
13
+ ObjectStack AI LLC's paid version(s) of the Licensed Work. For purposes
14
+ of this license:
15
+
16
+ A "competitive offering" is a Product that is offered to third
17
+ parties on a paid basis, including through paid support
18
+ arrangements, that significantly overlaps with the capabilities
19
+ of ObjectStack AI LLC's paid version(s) of the Licensed Work. If Your
20
+ Product is not a competitive offering when You first make it
21
+ generally available, it will not become a competitive offering
22
+ later due to ObjectStack AI LLC releasing a new version of the Licensed
23
+ Work with additional capabilities. In addition, Products that
24
+ are not provided on a paid basis are not competitive.
25
+
26
+ "Product" means software that is offered to end users to manage
27
+ in their own environments or offered as a service on a hosted
28
+ basis.
29
+
30
+ "Embedded" means including the source code or executable code
31
+ from the Licensed Work in a competitive offering. "Embedded"
32
+ also means packaging the competitive offering in such a way
33
+ that the Licensed Work must be accessed or downloaded for the
34
+ competitive offering to operate.
35
+
36
+ Hosting or using the Licensed Work(s) for internal purposes
37
+ within an organization is not considered a competitive
38
+ offering. ObjectStack AI LLC considers your organization to include all
39
+ of your affiliates under common control.
40
+
41
+ For binding interpretive guidance on using ObjectStack AI LLC products
42
+ under the Business Source License, please visit our FAQ.
43
+ (see LICENSING.md in this repository)
44
+ Change Date: Four years from the date the Licensed Work is published.
45
+ Change License: Apache License, Version 2.0
46
+
47
+ For information about alternative licensing arrangements for the Licensed Work,
48
+ please contact licensing@objectstack.dev.
49
+
50
+ Notice
51
+
52
+ Business Source License 1.1
53
+
54
+ Terms
55
+
56
+ The Licensor hereby grants you the right to copy, modify, create derivative
57
+ works, redistribute, and make non-production use of the Licensed Work. The
58
+ Licensor may make an Additional Use Grant, above, permitting limited production use.
59
+
60
+ Effective on the Change Date, or the fourth anniversary of the first publicly
61
+ available distribution of a specific version of the Licensed Work under this
62
+ License, whichever comes first, the Licensor hereby grants you rights under
63
+ the terms of the Change License, and the rights granted in the paragraph
64
+ above terminate.
65
+
66
+ If your use of the Licensed Work does not comply with the requirements
67
+ currently in effect as described in this License, you must purchase a
68
+ commercial license from the Licensor, its affiliated entities, or authorized
69
+ resellers, or you must refrain from using the Licensed Work.
70
+
71
+ All copies of the original and modified Licensed Work, and derivative works
72
+ of the Licensed Work, are subject to this License. This License applies
73
+ separately for each version of the Licensed Work and the Change Date may vary
74
+ for each version of the Licensed Work released by Licensor.
75
+
76
+ You must conspicuously display this License on each original or modified copy
77
+ of the Licensed Work. If you receive the Licensed Work in original or
78
+ modified form from a third party, the terms and conditions set forth in this
79
+ License apply to your use of that work.
80
+
81
+ Any use of the Licensed Work in violation of this License will automatically
82
+ terminate your rights under this License for the current and all other
83
+ versions of the Licensed Work.
84
+
85
+ This License does not grant you any right in any trademark or logo of
86
+ Licensor or its affiliates (provided that you may use a trademark or logo of
87
+ Licensor as expressly required by this License).
88
+
89
+ TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON
90
+ AN "AS IS" BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS,
91
+ EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF
92
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND
93
+ TITLE.
package/README.md ADDED
@@ -0,0 +1,528 @@
1
+ # @objectstack/mcp
2
+
3
+ MCP Runtime Server Plugin for ObjectStack — exposes AI tools, data resources, and agent prompts via the Model Context Protocol.
4
+
5
+ ## Features
6
+
7
+ - **Model Context Protocol (MCP)**: Expose ObjectStack resources to AI models via MCP
8
+ - **AI Tools**: Auto-generate MCP tools from ObjectStack actions and flows
9
+ - **Data Resources**: Expose objects, records, and metadata as MCP resources
10
+ - **Agent Prompts**: Register prompt templates for AI agents
11
+ - **Type-Safe**: Full Zod schema validation for tool inputs/outputs
12
+ - **Auto-Discovery**: MCP clients automatically discover available tools and resources
13
+ - **Streaming Support**: Stream large datasets and real-time updates
14
+ - **Security**: Built-in permission checks for tool execution
15
+
16
+ ## What is MCP?
17
+
18
+ Model Context Protocol (MCP) is an open protocol that standardizes how AI applications provide context to Large Language Models (LLMs). It allows AI models to:
19
+
20
+ - **Access Tools**: Execute functions and operations
21
+ - **Read Resources**: Access data and content
22
+ - **Use Prompts**: Leverage pre-defined prompt templates
23
+
24
+ Read more: [MCP Specification](https://modelcontextprotocol.io/)
25
+
26
+ ## Installation
27
+
28
+ ```bash
29
+ pnpm add @objectstack/mcp
30
+ ```
31
+
32
+ ## Basic Usage
33
+
34
+ ```typescript
35
+ import { defineStack } from '@objectstack/spec';
36
+ import { MCPServerPlugin } from '@objectstack/mcp';
37
+
38
+ const stack = defineStack({
39
+ plugins: [
40
+ MCPServerPlugin.configure({
41
+ serverName: 'objectstack-server',
42
+ version: '1.0.0',
43
+ autoRegisterTools: true,
44
+ }),
45
+ ],
46
+ });
47
+ ```
48
+
49
+ ## Configuration
50
+
51
+ ```typescript
52
+ interface MCPServerConfig {
53
+ /** Server name (shown to AI clients) */
54
+ serverName?: string;
55
+
56
+ /** Server version */
57
+ version?: string;
58
+
59
+ /** Auto-register tools from actions and flows */
60
+ autoRegisterTools?: boolean;
61
+
62
+ /** Auto-expose objects as resources */
63
+ autoExposeObjects?: boolean;
64
+
65
+ /** Enable streaming for large responses */
66
+ enableStreaming?: boolean;
67
+
68
+ /** Transport mechanism ('stdio' | 'http') */
69
+ transport?: 'stdio' | 'http';
70
+
71
+ /** HTTP port (if transport is 'http') */
72
+ port?: number;
73
+ }
74
+ ```
75
+
76
+ ## MCP Tools
77
+
78
+ ### Auto-Generated Tools
79
+
80
+ ObjectStack automatically exposes these operations as MCP tools:
81
+
82
+ ```typescript
83
+ // CRUD operations (auto-registered)
84
+ 'objectstack_find' // Query records
85
+ 'objectstack_findOne' // Get single record
86
+ 'objectstack_create' // Create record
87
+ 'objectstack_update' // Update record
88
+ 'objectstack_delete' // Delete record
89
+
90
+ // Metadata operations
91
+ 'objectstack_describeObject' // Get object schema
92
+ 'objectstack_listObjects' // List all objects
93
+ 'objectstack_listFields' // List object fields
94
+ ```
95
+
96
+ ### Custom Tools
97
+
98
+ Register custom tools that AI models can call:
99
+
100
+ ```typescript
101
+ import { defineTool } from '@objectstack/spec';
102
+
103
+ const calculateRevenueTool = defineTool({
104
+ name: 'calculate_revenue',
105
+ description: 'Calculate total revenue for an account',
106
+ inputSchema: {
107
+ type: 'object',
108
+ properties: {
109
+ accountId: { type: 'string', description: 'Account ID' },
110
+ startDate: { type: 'string', description: 'Start date (ISO 8601)' },
111
+ endDate: { type: 'string', description: 'End date (ISO 8601)' },
112
+ },
113
+ required: ['accountId'],
114
+ },
115
+ async execute({ accountId, startDate, endDate }) {
116
+ const opportunities = await kernel.getDriver().find({
117
+ object: 'opportunity',
118
+ filters: [
119
+ { field: 'account_id', operator: 'eq', value: accountId },
120
+ { field: 'stage', operator: 'eq', value: 'closed_won' },
121
+ { field: 'close_date', operator: 'gte', value: startDate },
122
+ { field: 'close_date', operator: 'lte', value: endDate },
123
+ ],
124
+ });
125
+
126
+ const total = opportunities.reduce((sum, opp) => sum + opp.amount, 0);
127
+
128
+ return {
129
+ accountId,
130
+ totalRevenue: total,
131
+ opportunityCount: opportunities.length,
132
+ };
133
+ },
134
+ });
135
+
136
+ // Register with MCP server
137
+ kernel.getService('mcp').registerTool(calculateRevenueTool);
138
+ ```
139
+
140
+ ## MCP Resources
141
+
142
+ ### Auto-Exposed Objects
143
+
144
+ All ObjectStack objects are automatically exposed as MCP resources:
145
+
146
+ ```
147
+ objectstack://objects/opportunity # Opportunity object schema
148
+ objectstack://objects/opportunity/records # All opportunity records
149
+ objectstack://objects/opportunity/123 # Specific opportunity record
150
+ ```
151
+
152
+ ### Custom Resources
153
+
154
+ Expose custom resources to AI models:
155
+
156
+ ```typescript
157
+ kernel.getService('mcp').registerResource({
158
+ uri: 'objectstack://reports/sales-pipeline',
159
+ name: 'Sales Pipeline Report',
160
+ description: 'Current sales pipeline with stages and amounts',
161
+ mimeType: 'application/json',
162
+ async read() {
163
+ const opportunities = await kernel.getDriver().find({
164
+ object: 'opportunity',
165
+ filters: [
166
+ { field: 'stage', operator: 'neq', value: 'closed_won' },
167
+ { field: 'stage', operator: 'neq', value: 'closed_lost' },
168
+ ],
169
+ });
170
+
171
+ const pipeline = opportunities.reduce((acc, opp) => {
172
+ acc[opp.stage] = (acc[opp.stage] || 0) + opp.amount;
173
+ return acc;
174
+ }, {});
175
+
176
+ return {
177
+ content: [
178
+ {
179
+ type: 'text',
180
+ text: JSON.stringify(pipeline, null, 2),
181
+ },
182
+ ],
183
+ };
184
+ },
185
+ });
186
+ ```
187
+
188
+ ## MCP Prompts
189
+
190
+ Register prompt templates that AI models can use:
191
+
192
+ ```typescript
193
+ kernel.getService('mcp').registerPrompt({
194
+ name: 'analyze_account',
195
+ description: 'Analyze an account and its opportunities',
196
+ arguments: [
197
+ {
198
+ name: 'accountId',
199
+ description: 'Account ID to analyze',
200
+ required: true,
201
+ },
202
+ ],
203
+ async render({ accountId }) {
204
+ const account = await kernel.getDriver().findOne({
205
+ object: 'account',
206
+ filters: [{ field: 'id', operator: 'eq', value: accountId }],
207
+ });
208
+
209
+ const opportunities = await kernel.getDriver().find({
210
+ object: 'opportunity',
211
+ filters: [{ field: 'account_id', operator: 'eq', value: accountId }],
212
+ });
213
+
214
+ return {
215
+ messages: [
216
+ {
217
+ role: 'user',
218
+ content: {
219
+ type: 'text',
220
+ text: `Analyze this account and provide insights:
221
+
222
+ Account: ${account.name}
223
+ Industry: ${account.industry}
224
+ Total Opportunities: ${opportunities.length}
225
+ Total Value: $${opportunities.reduce((sum, o) => sum + o.amount, 0)}
226
+
227
+ Opportunities:
228
+ ${opportunities.map(o => `- ${o.name} (${o.stage}): $${o.amount}`).join('\n')}
229
+
230
+ Please provide:
231
+ 1. Key insights about this account
232
+ 2. Risk assessment
233
+ 3. Recommendations for next steps`,
234
+ },
235
+ },
236
+ ],
237
+ };
238
+ },
239
+ });
240
+ ```
241
+
242
+ ## Using with AI Clients
243
+
244
+ ### Claude Desktop
245
+
246
+ Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:
247
+
248
+ ```json
249
+ {
250
+ "mcpServers": {
251
+ "objectstack": {
252
+ "command": "node",
253
+ "args": ["/path/to/your/objectstack/server.js"],
254
+ "env": {
255
+ "DATABASE_URL": "your-database-url"
256
+ }
257
+ }
258
+ }
259
+ }
260
+ ```
261
+
262
+ ### Cursor IDE
263
+
264
+ Add to `.cursor/mcp.json`:
265
+
266
+ ```json
267
+ {
268
+ "mcpServers": {
269
+ "objectstack": {
270
+ "command": "node",
271
+ "args": ["./server.js"]
272
+ }
273
+ }
274
+ }
275
+ ```
276
+
277
+ ### Cline VS Code Extension
278
+
279
+ Configure in Cline settings:
280
+
281
+ ```json
282
+ {
283
+ "cline.mcpServers": {
284
+ "objectstack": {
285
+ "command": "node",
286
+ "args": ["./server.js"]
287
+ }
288
+ }
289
+ }
290
+ ```
291
+
292
+ ## Server Implementation
293
+
294
+ ### Stdio Transport (Default)
295
+
296
+ ```typescript
297
+ // server.ts
298
+ import { defineStack } from '@objectstack/spec';
299
+ import { MCPServerPlugin } from '@objectstack/mcp';
300
+ import { DriverSql } from '@objectstack/driver-sql';
301
+
302
+ const stack = defineStack({
303
+ driver: DriverSql.configure({
304
+ client: 'better-sqlite3',
305
+ connection: { filename: process.env.DATABASE_URL ?? './data/app.db' },
306
+ }),
307
+ plugins: [
308
+ MCPServerPlugin.configure({
309
+ serverName: 'my-crm',
310
+ transport: 'stdio', // Claude Desktop, Cursor, Cline
311
+ }),
312
+ ],
313
+ });
314
+
315
+ await stack.boot();
316
+ ```
317
+
318
+ ### HTTP Transport
319
+
320
+ ```typescript
321
+ const stack = defineStack({
322
+ driver: DriverSql.configure({ /* ... */ }),
323
+ plugins: [
324
+ MCPServerPlugin.configure({
325
+ serverName: 'my-crm',
326
+ transport: 'http',
327
+ port: 3100,
328
+ }),
329
+ ],
330
+ });
331
+
332
+ await stack.boot();
333
+ // MCP server running on http://localhost:3100
334
+ ```
335
+
336
+ ## Advanced Features
337
+
338
+ ### Streaming Resources
339
+
340
+ ```typescript
341
+ kernel.getService('mcp').registerResource({
342
+ uri: 'objectstack://exports/opportunities-csv',
343
+ name: 'Opportunities Export (CSV)',
344
+ mimeType: 'text/csv',
345
+ async *stream() {
346
+ // Stream header
347
+ yield 'Name,Stage,Amount,Close Date\n';
348
+
349
+ // Stream records in batches
350
+ let offset = 0;
351
+ const batchSize = 100;
352
+
353
+ while (true) {
354
+ const batch = await kernel.getDriver().find({
355
+ object: 'opportunity',
356
+ limit: batchSize,
357
+ offset,
358
+ });
359
+
360
+ if (batch.length === 0) break;
361
+
362
+ for (const opp of batch) {
363
+ yield `${opp.name},${opp.stage},${opp.amount},${opp.close_date}\n`;
364
+ }
365
+
366
+ offset += batchSize;
367
+ }
368
+ },
369
+ });
370
+ ```
371
+
372
+ ### Tool Permissions
373
+
374
+ ```typescript
375
+ kernel.getService('mcp').registerTool({
376
+ name: 'delete_opportunity',
377
+ description: 'Delete an opportunity',
378
+ permissions: ['opportunity:delete'], // Require permission
379
+ inputSchema: {
380
+ type: 'object',
381
+ properties: {
382
+ id: { type: 'string' },
383
+ },
384
+ required: ['id'],
385
+ },
386
+ async execute({ id }, context) {
387
+ // context includes userId, permissions, etc.
388
+ if (!context.hasPermission('opportunity:delete')) {
389
+ throw new Error('Permission denied');
390
+ }
391
+
392
+ await kernel.getDriver().delete({
393
+ object: 'opportunity',
394
+ filters: [{ field: 'id', operator: 'eq', value: id }],
395
+ });
396
+
397
+ return { success: true, deleted: id };
398
+ },
399
+ });
400
+ ```
401
+
402
+ ### Dynamic Tool Registration
403
+
404
+ ```typescript
405
+ // Register tools from flow definitions
406
+ const flows = await kernel.getMetadata('flow');
407
+
408
+ for (const flow of flows) {
409
+ kernel.getService('mcp').registerTool({
410
+ name: `flow_${flow.name}`,
411
+ description: flow.description,
412
+ inputSchema: generateSchemaFromFlow(flow),
413
+ async execute(inputs) {
414
+ return await kernel.executeFlow(flow.name, inputs);
415
+ },
416
+ });
417
+ }
418
+ ```
419
+
420
+ ## Server Capabilities
421
+
422
+ The MCP server exposes these capabilities:
423
+
424
+ ```json
425
+ {
426
+ "capabilities": {
427
+ "tools": {
428
+ "listChanged": true
429
+ },
430
+ "resources": {
431
+ "subscribe": true,
432
+ "listChanged": true
433
+ },
434
+ "prompts": {
435
+ "listChanged": true
436
+ },
437
+ "logging": {},
438
+ "experimental": {
439
+ "streaming": true
440
+ }
441
+ }
442
+ }
443
+ ```
444
+
445
+ ## Best Practices
446
+
447
+ 1. **Tool Design**: Keep tools focused and well-documented
448
+ 2. **Resource Naming**: Use clear, hierarchical URI schemes
449
+ 3. **Prompt Templates**: Make prompts flexible with arguments
450
+ 4. **Error Handling**: Always return helpful error messages
451
+ 5. **Permissions**: Check permissions before tool execution
452
+ 6. **Performance**: Use streaming for large datasets
453
+ 7. **Versioning**: Version your server and tools
454
+
455
+ ## Debugging
456
+
457
+ Enable debug logging:
458
+
459
+ ```typescript
460
+ MCPServerPlugin.configure({
461
+ serverName: 'my-crm',
462
+ debug: true, // Log all MCP messages
463
+ });
464
+ ```
465
+
466
+ View MCP messages in client:
467
+ - **Claude Desktop**: Check logs in `~/Library/Logs/Claude/mcp*.log`
468
+ - **Cursor**: Check Output panel → MCP Server
469
+ - **Cline**: Check extension logs
470
+
471
+ ## Example: Complete CRM Server
472
+
473
+ ```typescript
474
+ import { defineStack, defineTool } from '@objectstack/spec';
475
+ import { MCPServerPlugin } from '@objectstack/mcp';
476
+
477
+ const stack = defineStack({
478
+ driver: /* ... */,
479
+ plugins: [
480
+ MCPServerPlugin.configure({
481
+ serverName: 'crm-assistant',
482
+ autoRegisterTools: true,
483
+ }),
484
+ ],
485
+ });
486
+
487
+ await stack.boot();
488
+
489
+ const mcp = stack.kernel.getService('mcp');
490
+
491
+ // Register custom tools
492
+ mcp.registerTool(defineTool({
493
+ name: 'forecast_revenue',
494
+ description: 'Forecast revenue based on pipeline',
495
+ async execute() {
496
+ // Implementation
497
+ },
498
+ }));
499
+
500
+ // Register custom resources
501
+ mcp.registerResource({
502
+ uri: 'objectstack://dashboards/sales',
503
+ name: 'Sales Dashboard',
504
+ async read() {
505
+ // Implementation
506
+ },
507
+ });
508
+
509
+ // Register prompts
510
+ mcp.registerPrompt({
511
+ name: 'weekly_report',
512
+ description: 'Generate weekly sales report',
513
+ async render() {
514
+ // Implementation
515
+ },
516
+ });
517
+ ```
518
+
519
+ ## License
520
+
521
+ Apache-2.0. See [LICENSING.md](../../LICENSING.md).
522
+
523
+ ## See Also
524
+
525
+ - [Model Context Protocol Specification](https://modelcontextprotocol.io/)
526
+ - [MCP TypeScript SDK](https://github.com/modelcontextprotocol/typescript-sdk)
527
+ - [@objectstack/spec/ai](../../spec/src/ai/)
528
+ - [Building MCP Servers Guide](/content/docs/guides/mcp/)