@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.
@@ -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 };