@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 +93 -0
- package/README.md +528 -0
- package/dist/index.cjs +817 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +284 -0
- package/dist/index.d.ts +284 -0
- package/dist/index.js +785 -0
- package/dist/index.js.map +1 -0
- package/package.json +58 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
import { Plugin, PluginContext } from '@objectstack/core';
|
|
2
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
|
+
import { AIToolDefinition, ToolCallPart, ToolResultPart, Logger, IMetadataService, IDataEngine } from '@objectstack/spec/contracts';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Configuration options for the MCPServerPlugin.
|
|
7
|
+
*/
|
|
8
|
+
interface MCPServerPluginOptions {
|
|
9
|
+
/** Override MCP server name. Defaults to 'objectstack'. */
|
|
10
|
+
name?: string;
|
|
11
|
+
/** Override MCP server version. Defaults to package version. */
|
|
12
|
+
version?: string;
|
|
13
|
+
/** Transport mode: 'stdio' (default). */
|
|
14
|
+
transport?: 'stdio' | 'http';
|
|
15
|
+
/** Whether to auto-start the MCP server. Defaults to false (manual start via env var). */
|
|
16
|
+
autoStart?: boolean;
|
|
17
|
+
/** Custom instructions for the MCP server. */
|
|
18
|
+
instructions?: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* MCPServerPlugin — Kernel plugin that exposes ObjectStack as an MCP server.
|
|
22
|
+
*
|
|
23
|
+
* Lifecycle:
|
|
24
|
+
* 1. **init** — Creates {@link MCPServerRuntime} and registers as `'mcp'` service.
|
|
25
|
+
* 2. **start** — Bridges ToolRegistry, MetadataService, DataEngine, and Agents
|
|
26
|
+
* to the MCP server. Starts the transport if `autoStart` is enabled or
|
|
27
|
+
* the `OS_MCP_SERVER_ENABLED` environment variable is set.
|
|
28
|
+
* 3. **destroy** — Stops the MCP transport.
|
|
29
|
+
*
|
|
30
|
+
* Environment Variables:
|
|
31
|
+
* - `OS_MCP_SERVER_ENABLED=true` — Enable MCP server at startup
|
|
32
|
+
* - `OS_MCP_SERVER_NAME` — Override server name
|
|
33
|
+
* - `OS_MCP_SERVER_TRANSPORT` — Override transport ('stdio' | 'http')
|
|
34
|
+
* (legacy `MCP_SERVER_*` names still honoured with a deprecation warning)
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```ts
|
|
38
|
+
* import { LiteKernel } from '@objectstack/core';
|
|
39
|
+
* import { MCPServerPlugin } from '@objectstack/mcp';
|
|
40
|
+
*
|
|
41
|
+
* const kernel = new LiteKernel();
|
|
42
|
+
* kernel.use(new MCPServerPlugin({ autoStart: true }));
|
|
43
|
+
* await kernel.bootstrap();
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
declare class MCPServerPlugin implements Plugin {
|
|
47
|
+
name: string;
|
|
48
|
+
version: string;
|
|
49
|
+
type: "standard";
|
|
50
|
+
dependencies: string[];
|
|
51
|
+
private runtime?;
|
|
52
|
+
private readonly options;
|
|
53
|
+
constructor(options?: MCPServerPluginOptions);
|
|
54
|
+
init(ctx: PluginContext): Promise<void>;
|
|
55
|
+
start(ctx: PluginContext): Promise<void>;
|
|
56
|
+
destroy(): Promise<void>;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Minimal ToolRegistry interface consumed by the MCP bridge.
|
|
61
|
+
*
|
|
62
|
+
* Matches the public API of `ToolRegistry` from `@objectstack/service-ai`
|
|
63
|
+
* without creating a hard dependency on that package.
|
|
64
|
+
*/
|
|
65
|
+
interface ToolRegistry {
|
|
66
|
+
/** Return all registered tool definitions. */
|
|
67
|
+
getAll(): AIToolDefinition[];
|
|
68
|
+
/** Execute a tool call and return the result. */
|
|
69
|
+
execute(toolCall: ToolCallPart): Promise<ToolExecutionResult>;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Extended ToolResultPart with isError flag, matching service-ai's ToolExecutionResult.
|
|
73
|
+
*/
|
|
74
|
+
interface ToolExecutionResult extends ToolResultPart {
|
|
75
|
+
isError?: boolean;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
interface McpObjectSummary {
|
|
79
|
+
name: string;
|
|
80
|
+
label?: string;
|
|
81
|
+
fieldCount?: number;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Data access seam for the HTTP MCP tools. Implemented by the runtime/dispatcher
|
|
85
|
+
* so execution flows through the existing permission + RLS path bound to the
|
|
86
|
+
* caller's ExecutionContext. Every method runs AS the authenticated principal.
|
|
87
|
+
*/
|
|
88
|
+
interface McpDataBridge {
|
|
89
|
+
listObjects(): Promise<McpObjectSummary[]>;
|
|
90
|
+
describeObject(name: string): Promise<unknown | null>;
|
|
91
|
+
query(object: string, opts: {
|
|
92
|
+
where?: Record<string, unknown>;
|
|
93
|
+
fields?: string[];
|
|
94
|
+
limit?: number;
|
|
95
|
+
offset?: number;
|
|
96
|
+
orderBy?: Array<{
|
|
97
|
+
field: string;
|
|
98
|
+
order: 'asc' | 'desc';
|
|
99
|
+
}>;
|
|
100
|
+
}): Promise<unknown>;
|
|
101
|
+
get(object: string, id: string): Promise<unknown>;
|
|
102
|
+
create(object: string, data: Record<string, unknown>): Promise<unknown>;
|
|
103
|
+
update(object: string, id: string, data: Record<string, unknown>): Promise<unknown>;
|
|
104
|
+
remove(object: string, id: string): Promise<unknown>;
|
|
105
|
+
}
|
|
106
|
+
interface RegisterObjectToolsOptions {
|
|
107
|
+
/** Expose `sys_*` system objects too. Default false (fail-closed). */
|
|
108
|
+
allowSystemObjects?: boolean;
|
|
109
|
+
/** Hard cap on `query_records` page size. Default 50. */
|
|
110
|
+
maxQueryLimit?: number;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Register the object-CRUD tool set on a fresh per-request {@link McpServer}.
|
|
114
|
+
* All execution is delegated to `bridge`, which is bound to the caller's
|
|
115
|
+
* principal by the runtime.
|
|
116
|
+
*/
|
|
117
|
+
declare function registerObjectTools(server: McpServer, bridge: McpDataBridge, options?: RegisterObjectToolsOptions): void;
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Configuration for the MCP Server Runtime.
|
|
121
|
+
*/
|
|
122
|
+
interface MCPServerRuntimeConfig {
|
|
123
|
+
/** Human-readable server name. */
|
|
124
|
+
name?: string;
|
|
125
|
+
/** Server version (semver). */
|
|
126
|
+
version?: string;
|
|
127
|
+
/** Optional instructions describing how to use the server. */
|
|
128
|
+
instructions?: string;
|
|
129
|
+
/** Transport mode: 'stdio' (default) or 'http'. */
|
|
130
|
+
transport?: 'stdio' | 'http';
|
|
131
|
+
/** Logger instance. */
|
|
132
|
+
logger?: Logger;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* MCPServerRuntime — Bridges ObjectStack kernel services to the Model Context Protocol.
|
|
136
|
+
*
|
|
137
|
+
* Responsibilities:
|
|
138
|
+
* 1. Bridge ToolRegistry → MCP tools (all registered AI tools)
|
|
139
|
+
* 2. Bridge IMetadataService → MCP resources (object schemas, metadata types)
|
|
140
|
+
* 3. Bridge IDataEngine → MCP resources (record access by URI)
|
|
141
|
+
* 4. Bridge Agent definitions → MCP prompts (agent instructions)
|
|
142
|
+
*
|
|
143
|
+
* Architecture:
|
|
144
|
+
* ```
|
|
145
|
+
* ToolRegistry (service-ai) ──┐
|
|
146
|
+
* IMetadataService (metadata) ─┼──→ MCPServerRuntime ──→ McpServer (SDK)
|
|
147
|
+
* IDataEngine (objectql) ──┤ │
|
|
148
|
+
* Agent definitions ──┘ ├── stdio transport
|
|
149
|
+
* └── http transport (future)
|
|
150
|
+
* ```
|
|
151
|
+
*/
|
|
152
|
+
declare class MCPServerRuntime {
|
|
153
|
+
private readonly mcpServer;
|
|
154
|
+
private readonly config;
|
|
155
|
+
private transport;
|
|
156
|
+
private started;
|
|
157
|
+
constructor(config?: MCPServerRuntimeConfig);
|
|
158
|
+
/** The underlying McpServer instance (for advanced use cases). */
|
|
159
|
+
get server(): McpServer;
|
|
160
|
+
/** Whether the server is currently connected and running. */
|
|
161
|
+
get isStarted(): boolean;
|
|
162
|
+
/**
|
|
163
|
+
* Extract the text value from a ToolExecutionResult's output.
|
|
164
|
+
*
|
|
165
|
+
* The output may be a `{ type: 'text', value: string }` object (from the
|
|
166
|
+
* Vercel AI SDK ToolResultPart) or any serialisable value.
|
|
167
|
+
*/
|
|
168
|
+
private static formatToolOutput;
|
|
169
|
+
/**
|
|
170
|
+
* Bridge all tools from the ToolRegistry to MCP tools.
|
|
171
|
+
*
|
|
172
|
+
* Each registered tool becomes an MCP tool with the same name, description,
|
|
173
|
+
* and JSON Schema parameters. The handler delegates to the ToolRegistry's
|
|
174
|
+
* execute path.
|
|
175
|
+
*/
|
|
176
|
+
bridgeTools(toolRegistry: ToolRegistry): void;
|
|
177
|
+
/**
|
|
178
|
+
* Register a single tool on the MCP server from an AIToolDefinition.
|
|
179
|
+
*/
|
|
180
|
+
private registerToolFromDefinition;
|
|
181
|
+
/**
|
|
182
|
+
* Check if a tool is read-only (data query tools).
|
|
183
|
+
*/
|
|
184
|
+
private isReadOnlyTool;
|
|
185
|
+
/**
|
|
186
|
+
* Check if a tool performs destructive operations.
|
|
187
|
+
*/
|
|
188
|
+
private isDestructiveTool;
|
|
189
|
+
/**
|
|
190
|
+
* Bridge metadata service and data engine to MCP resources.
|
|
191
|
+
*
|
|
192
|
+
* Exposes:
|
|
193
|
+
* - `objectstack://objects` — List all data objects
|
|
194
|
+
* - `objectstack://objects/{objectName}` — Get object schema
|
|
195
|
+
* - `objectstack://objects/{objectName}/records/{recordId}` — Get a specific record
|
|
196
|
+
* - `objectstack://metadata/types` — List all metadata types
|
|
197
|
+
*/
|
|
198
|
+
bridgeResources(metadataService: IMetadataService, dataEngine?: IDataEngine): void;
|
|
199
|
+
/**
|
|
200
|
+
* Bridge registered agents to MCP prompts.
|
|
201
|
+
*
|
|
202
|
+
* Each active agent becomes an MCP prompt with:
|
|
203
|
+
* - Name matching the agent name
|
|
204
|
+
* - System message from agent instructions
|
|
205
|
+
* - Optional context arguments (objectName, recordId, viewName)
|
|
206
|
+
*/
|
|
207
|
+
bridgePrompts(metadataService: IMetadataService): void;
|
|
208
|
+
/**
|
|
209
|
+
* Start the MCP server with the configured transport.
|
|
210
|
+
*
|
|
211
|
+
* For stdio transport, this connects to process stdin/stdout.
|
|
212
|
+
*/
|
|
213
|
+
start(): Promise<void>;
|
|
214
|
+
/**
|
|
215
|
+
* Stop the MCP server and disconnect the transport.
|
|
216
|
+
*/
|
|
217
|
+
stop(): Promise<void>;
|
|
218
|
+
/**
|
|
219
|
+
* Handle one MCP request over the **Streamable HTTP** transport (Web Standard
|
|
220
|
+
* `Request`/`Response`), the network-reachable surface for external agents.
|
|
221
|
+
*
|
|
222
|
+
* Stateless by design: a fresh {@link McpServer} + transport is built per
|
|
223
|
+
* request (the SDK-recommended pattern for stateless HTTP — it avoids any
|
|
224
|
+
* cross-request session/request-id collision and keeps each call isolated).
|
|
225
|
+
* The tool set is the object-CRUD bridge, bound to the **caller's principal**
|
|
226
|
+
* via `bridge`; the runtime wires that bridge to the existing permission +
|
|
227
|
+
* RLS path, so an external agent can never exceed the key's authority.
|
|
228
|
+
*
|
|
229
|
+
* Only the object-CRUD tools are exposed here — the internal AI/authoring
|
|
230
|
+
* toolRegistry (which can mutate metadata) is deliberately NOT bridged onto
|
|
231
|
+
* the external surface.
|
|
232
|
+
*
|
|
233
|
+
* @param request The inbound Web `Request` (headers/method/url).
|
|
234
|
+
* @param opts.bridge Principal-bound data accessor (required to expose tools).
|
|
235
|
+
* @param opts.parsedBody Pre-parsed JSON-RPC body (the dispatcher already read it).
|
|
236
|
+
* @param opts.authInfo Optional auth info forwarded to message handlers.
|
|
237
|
+
* @param opts.toolOptions Object-tool exposure options (system objects, limits).
|
|
238
|
+
*/
|
|
239
|
+
handleHttpRequest(request: Request, opts?: {
|
|
240
|
+
bridge?: McpDataBridge;
|
|
241
|
+
parsedBody?: unknown;
|
|
242
|
+
authInfo?: unknown;
|
|
243
|
+
toolOptions?: RegisterObjectToolsOptions;
|
|
244
|
+
}): Promise<Response>;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* skill — the generic, portable ObjectStack Agent Skill.
|
|
249
|
+
*
|
|
250
|
+
* Per ADR-0036 (Amendment C): the cross-agent distributable is ONE generic
|
|
251
|
+
* Skill, not per-app artifacts and not hand-maintained vendor config snippets.
|
|
252
|
+
* Agent Skills (`SKILL.md`) is an open, cross-platform standard (Claude Code,
|
|
253
|
+
* OpenAI Codex, Gemini CLI, Copilot, Cursor, …), so this single skill teaches
|
|
254
|
+
* any skills-capable agent how to drive an ObjectStack environment over MCP.
|
|
255
|
+
*
|
|
256
|
+
* The skill content is GENERIC — it never enumerates a tenant's schema (that is
|
|
257
|
+
* discovered live via the `list_objects` / `describe_object` MCP tools). Only
|
|
258
|
+
* the connection URL is environment-specific, slotted in by
|
|
259
|
+
* {@link renderSkillMarkdown}. So one skill install works for every env and
|
|
260
|
+
* every app the caller's key can reach; building a new app needs no reinstall.
|
|
261
|
+
*
|
|
262
|
+
* This module is the single source of truth for the skill; serve it (objectui /
|
|
263
|
+
* cloud) by calling {@link renderSkillMarkdown} with the env's MCP URL.
|
|
264
|
+
*/
|
|
265
|
+
/** Skill identity (mirrors the `SKILL.md` YAML frontmatter). */
|
|
266
|
+
declare const OBJECTSTACK_SKILL_NAME = "objectstack";
|
|
267
|
+
declare const OBJECTSTACK_SKILL_DESCRIPTION: string;
|
|
268
|
+
interface RenderSkillOptions {
|
|
269
|
+
/**
|
|
270
|
+
* The environment's MCP endpoint, e.g. `https://acme.objectos.app/api/v1/mcp`.
|
|
271
|
+
* When omitted a clearly-marked placeholder is used so the skill is still
|
|
272
|
+
* valid and self-explanatory.
|
|
273
|
+
*/
|
|
274
|
+
mcpUrl?: string;
|
|
275
|
+
/** Optional human label for the environment, shown in the intro. */
|
|
276
|
+
envName?: string;
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Render the full `SKILL.md` (YAML frontmatter + body). Pass the env's MCP URL
|
|
280
|
+
* to produce a ready-to-install skill; the body is otherwise generic.
|
|
281
|
+
*/
|
|
282
|
+
declare function renderSkillMarkdown(options?: RenderSkillOptions): string;
|
|
283
|
+
|
|
284
|
+
export { MCPServerPlugin, type MCPServerPluginOptions, MCPServerRuntime, type MCPServerRuntimeConfig, type McpDataBridge, type McpObjectSummary, OBJECTSTACK_SKILL_DESCRIPTION, OBJECTSTACK_SKILL_NAME, type RegisterObjectToolsOptions, type RenderSkillOptions, registerObjectTools, renderSkillMarkdown };
|