Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .changeset/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
"@objectstack/plugin-dev",
"@objectstack/plugin-email",
"@objectstack/plugin-hono-server",
"@objectstack/plugin-mcp-server",
"@objectstack/mcp",
"@objectstack/plugin-msw",
"@objectstack/plugin-org-scoping",
"@objectstack/plugin-reports",
Expand Down
4 changes: 2 additions & 2 deletions .changeset/mcp-streamable-http-transport.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
'@objectstack/plugin-mcp-server': minor
'@objectstack/mcp': minor
'@objectstack/runtime': minor
---

Expand All @@ -10,7 +10,7 @@ Cursor) could not connect to a hosted env. This adds the **Streamable HTTP**
transport and wires it into the runtime's request path, building on the Phase 1a
`sys_api_key` auth foundation.

- **`@objectstack/plugin-mcp-server`**
- **`@objectstack/mcp`** (renamed from `@objectstack/plugin-mcp-server` — see the rename changeset)
- `MCPServerRuntime.handleHttpRequest(request, { bridge, parsedBody })` —
serves one MCP request over the Web-standard `WebStandardStreamableHTTPServerTransport`
(runs on Node 18+, Workers, Deno, Bun). **Stateless**: a fresh, isolated
Expand Down
18 changes: 18 additions & 0 deletions .changeset/rename-mcp-package.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
'@objectstack/mcp': major
'@objectstack/cli': patch
---

refactor(mcp)!: rename `@objectstack/plugin-mcp-server` → `@objectstack/mcp` (ADR-0036)

The outbound MCP-server package drops the legacy `plugin-` prefix and moves to
the top level (`packages/mcp`), parallel to `@objectstack/rest` — both are "your
app exposed over a protocol". Inbound MCP (consuming external servers) stays
`@objectstack/connector-mcp`.

**Breaking:** the package name changed. Update imports
`@objectstack/plugin-mcp-server` → `@objectstack/mcp`. The exported API
(`MCPServerPlugin`, `MCPServerRuntime`, `registerObjectTools`, `McpDataBridge`,
…) is unchanged. The internal plugin id is now `com.objectstack.mcp`. Pre-launch
clean break — no compatibility shim (only `@objectstack/cli` depended on it
internally).
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ Cloud, package registry, and environment management subcommands (`os publish`, `
| Package | Description |
| :--- | :--- |
| [`@objectstack/plugin-hono-server`](packages/plugins/plugin-hono-server) | Hono-based HTTP server plugin |
| [`@objectstack/plugin-mcp-server`](packages/plugins/plugin-mcp-server) | Model Context Protocol server — exposes ObjectStack to AI agents |
| [`@objectstack/mcp`](packages/mcp) | Model Context Protocol server — exposes ObjectStack to AI agents |
| [`@objectstack/plugin-auth`](packages/plugins/plugin-auth) | Authentication plugin (better-auth) |
| [`@objectstack/plugin-security`](packages/plugins/plugin-security) | RBAC, Row-Level Security, Field-Level Security |
| [`@objectstack/plugin-sharing`](packages/plugins/plugin-sharing) | Record-level sharing — `sys_record_share` + enforcement middleware |
Expand Down
2 changes: 1 addition & 1 deletion RELEASE_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ Prepare all 42 packages under `@objectstack/*` for formal public release on npm
| Client / DX | 5 | `client`, `client-react`, `cli`, `create-objectstack`, `vscode-objectstack` |
| Adapters | 7 | `express`, `fastify`, `hono`, `nestjs`, `nextjs`, `nuxt`, `sveltekit` |
| Drivers | 3 | `driver-memory`, `driver-sql`, `driver-turso` |
| Plugins | 8 | `plugin-auth`, `plugin-security`, `plugin-audit`, `plugin-hono-server`, `plugin-mcp-server`, `plugin-msw`, `plugin-dev`, `plugin-setup` |
| Plugins | 8 | `plugin-auth`, `plugin-security`, `plugin-audit`, `plugin-hono-server`, `mcp`, `plugin-msw`, `plugin-dev`, `plugin-setup` |
| Services | 12 | `service-ai`, `service-analytics`, `service-automation`, `service-cache`, `service-feed`, `service-i18n`, `service-job`, `service-package`, `service-queue`, `service-realtime`, `service-storage`, `service-tenant` |

### ✅ Release readiness checklist
Expand Down
6 changes: 3 additions & 3 deletions content/docs/guides/packages.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ ObjectStack is organized into **70 package manifests** across multiple categorie
| **Client / DX** | 5 | `client`, `client-react`, `cli`, `create-objectstack`, `vscode-objectstack` |
| **Framework adapters** | 7 | `express`, `fastify`, `hono`, `nestjs`, `nextjs`, `nuxt`, `sveltekit` |
| **Drivers** | 4 | `driver-memory`, `driver-sql`, `driver-sqlite-wasm`, `driver-mongodb` |
| **Plugins** | 22 | `plugin-auth`, `plugin-security`, `plugin-org-scoping`, `plugin-audit`, `plugin-approvals`, `plugin-sharing`, `plugin-email`, `plugin-webhooks`, `plugin-reports`, `plugin-hono-server`, `plugin-mcp-server`, `plugin-msw`, `plugin-dev`, trigger plugins, and knowledge/embedder plugins |
| **Plugins** | 22 | `plugin-auth`, `plugin-security`, `plugin-org-scoping`, `plugin-audit`, `plugin-approvals`, `plugin-sharing`, `plugin-email`, `plugin-webhooks`, `plugin-reports`, `plugin-hono-server`, `mcp`, `plugin-msw`, `plugin-dev`, trigger plugins, and knowledge/embedder plugins |
| **Platform services** | 17 | `service-ai`, `service-analytics`, `service-automation`, `service-cache`, `service-cluster`, `service-cluster-redis`, `service-datasource`, `service-feed`, `service-i18n`, `service-job`, `service-knowledge`, `service-messaging`, `service-package`, `service-queue`, `service-realtime`, `service-settings`, `service-storage` |


Expand Down Expand Up @@ -330,13 +330,13 @@ All services implement contracts from `@objectstack/spec/contracts` and are kern
- **When to use**: SOC 2, HIPAA, GDPR compliance, security monitoring
- **README**: [View README](/packages/plugins/plugin-audit/README.md)

### @objectstack/plugin-mcp-server
### @objectstack/mcp

**MCP Server Plugin** — Expose ObjectStack via Model Context Protocol.

- **Features**: AI tools, data resources, prompt templates for Claude, Cursor, Cline
- **When to use**: AI agent integration, MCP-compatible tools
- **README**: [View README](/packages/plugins/plugin-mcp-server/README.md)
- **README**: [View README](/packages/mcp/README.md)

### @objectstack/plugin-hono-server

Expand Down
2 changes: 1 addition & 1 deletion content/docs/references/ai/mcp.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ MCP itself is an external protocol defined by Anthropic

MCP's wire format, transport, or message shapes — that is the job

of the `@modelcontextprotocol/sdk` consumed by `plugin-mcp-server`.
of the `@modelcontextprotocol/sdk` consumed by `mcp`.

This file defines only the two things the *platform* needs:

Expand Down
27 changes: 21 additions & 6 deletions docs/adr/0036-app-as-rest-api-and-mcp-server.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,35 @@
**Status**: Proposed (2026-06-06)
**Deciders**: ObjectStack Protocol Architects
**Builds on**: [ADR-0011](./0011-actions-as-ai-tools.md) (actions/objects as AI tools), [ADR-0024](./0024-mcp-connectors.md) (MCP as connectors — the *inbound* sibling: ObjectStack **consuming** external MCP servers; this ADR is the *outbound* direction), [ADR-0033](./0033-ai-assisted-metadata-authoring.md) (AI builds the metadata; publishing makes it live)
**Consumers**: `@objectstack/rest` (REST CRUD + `/api/v1/discovery`), new HTTP transport in `@objectstack/plugin-mcp-server`, `@objectstack/platform-objects` (`sys_api_key`), `../objectui` (Developer Hub → new Integrations page; publish surface), `../cloud` (per-env public hostname = the API/MCP base)
**Consumers**: `@objectstack/rest` (REST CRUD + `/api/v1/discovery`), new HTTP transport in `@objectstack/mcp`, `@objectstack/platform-objects` (`sys_api_key`), `../objectui` (Developer Hub → new Integrations page; publish surface), `../cloud` (per-env public hostname = the API/MCP base)

**Premise**: pre-launch, no back-compat debt — specify the target end-state directly.

**Design center**: **the moment you build an object in ObjectStack, it is already a programmable REST API and an agent-ready MCP toolset — we just have to make that visible and one-click connectable.** This is the differentiator Lovable / Airtable / Power Apps structurally cannot match: their output is a screen; ours is a *governed data backend* that any program or AI agent can drive. The magic moment (one sentence → a working, populated app) should end not at "here's your screen" but at **"here's your screen — and here's the API + the agent tools it exposes."**

---

## Amendment (2026-06-07) — naming, granularity, and distribution

After Phase 1a/2 landed, three decisions refine (and in one case supersede) the sections below. They take precedence where they conflict.

**A. Package name → `@objectstack/mcp`.** The outbound MCP-server package was renamed from `@objectstack/plugin-mcp-server` (legacy `plugin-` prefix) to **`@objectstack/mcp`** at the top level (`packages/mcp`), parallel to `@objectstack/rest`. Both are "your app exposed over a protocol", so `rest` (old surface) + `mcp` (new surface) sit as peers; inbound MCP (consuming external servers) stays `@objectstack/connector-mcp`. The old name is removed (pre-launch clean break; only internal `@objectstack/cli` depended on it).

**B. Granularity is the *environment*, not the app.** One MCP server per env (`<env-host>/api/v1/mcp`) covers **all** of that env's apps — apps are metadata groupings of objects, and the data surface is objects. A customer with dozens of apps in one env has **one** MCP connection, not dozens. Dynamic apps are a non-issue: tool discovery is **live** (`list_objects` / `describe_object`), so a newly built app shows up on the next call with **zero reinstall**. Narrowing an agent to a subset of objects/apps is done via **`sys_api_key.scopes`** (per-key), never by standing up separate servers.

**C. Distribution = "skills + MCP", not vendor config snippets** (supersedes §3/§4's "generate `claude_desktop_config.json` / Cursor snippet" as the *primary* artifact). Verified 2026-06: **Agent Skills (`SKILL.md`) is now an open, cross-platform standard** (Claude Code, OpenAI Codex CLI, Gemini CLI, GitHub Copilot, Cursor, Cline, Windsurf, …; MCP under the Linux Foundation). Skills and MCP are **complementary**: MCP = the live, authenticated, RLS-governed access layer (the moat — a static skill can never be the live data gateway to a specific tenant env); a Skill = the portable "how to use it" layer on top. So the primary cross-agent distributable is **one generic ObjectStack Skill** (install once; teaches the tool conventions, query/RLS idioms, workflows — it does **not** enumerate schema, which is discovered live), plus the env's remote-MCP URL + a **show-once `sys_api_key`**. A one-click "Add to Claude/Cursor" deeplink (or a `.claude-plugin` bundle that registers the MCP server) is a convenience on top, not the core artifact — we do not hand-maintain N vendor snippets.

---

## TL;DR

A metadata-driven ObjectStack app **already** auto-generates a full REST CRUD API (`/api/v1/data/{object}`) discoverable at `/api/v1/discovery`, and the `plugin-mcp-server` **already** maps every object's CRUD (and the registered AI tools) to MCP tools. Two things are missing to turn that latent capability into a product: (1) the MCP server only speaks **stdio**, so a remote agent (Claude Desktop / Cursor) can't connect to a cloud env; (2) none of it is **surfaced** — a user who just built an app has no idea it's an API, no self-serve key, no connect button.
A metadata-driven ObjectStack app **already** auto-generates a full REST CRUD API (`/api/v1/data/{object}`) discoverable at `/api/v1/discovery`, and the `@objectstack/mcp` **already** maps every object's CRUD (and the registered AI tools) to MCP tools. Two things are missing to turn that latent capability into a product: (1) the MCP server only speaks **stdio**, so a remote agent (Claude Desktop / Cursor) can't connect to a cloud env; (2) none of it is **surfaced** — a user who just built an app has no idea it's an API, no self-serve key, no connect button.

**Decision.** Treat "expose this app as an API + MCP server" as a first-class, open framework capability and surface it right after build:

1. **REST**: keep the auto-generated CRUD + discovery (no change); **surface** it (base URL, per-object endpoints, sample code, the existing API Console).
2. **Auth**: per-env, self-serve **API keys** (`sys_api_key`, modelled but **not yet enforced** — wiring the key Bearer into the auth path is Phase 1a) — Bearer tokens that resolve to a principal and run under the key's existing permissions + RLS; a show-once generation UX.
3. **MCP**: add an **HTTP transport** to `plugin-mcp-server` (a stable `/api/v1/mcp` endpoint, authed by the same Bearer), and **generate the Claude/Cursor connection config** for the env.
3. **MCP**: add an **HTTP transport** to `@objectstack/mcp` (a stable `/api/v1/mcp` endpoint, authed by the same Bearer), and **generate the Claude/Cursor connection config** for the env.
4. **Surface**: a Developer-Hub **Integrations & APIs** page + a "View API / Connect an agent" affordance on publish success.

**Open-core boundary**: the REST serve path, the MCP HTTP transport, discovery, and `sys_api_key` are the **open mechanism** (framework); the AI/intelligence that *authored* the app stays closed; the surfacing UI lives in objectui.
Expand All @@ -35,7 +47,7 @@ A metadata-driven ObjectStack app **already** auto-generates a full REST CRUD AP
| REST CRUD per object (`/api/v1/data/{object}` + OData query) | `@objectstack/rest` `registerCrudEndpoints()` | ✅ auto-generated on publish |
| API discovery (`/api/v1/discovery`) | `@objectstack/rest` | ✅ |
| API Console (interactive REST debugger) | objectui `apps/console/.../developer/ApiConsolePage` | ✅ shipped |
| MCP server: object CRUD + AI tools → MCP tools | `@objectstack/plugin-mcp-server` | ✅ but **stdio only**, default off |
| MCP server: object CRUD + AI tools → MCP tools | `@objectstack/mcp` | ✅ but **stdio only**, default off |
| Per-user/env API keys (create/revoke, key returned once) | `platform-objects/.../sys-api-key.object.ts` | ⚠️ **model only — NOT enforced for auth** (no key-verification path; the data API accepts only the better-auth session); no UI |
| Per-env public hostname (`<env>.objectos.app`) = API/MCP base | cloud env registry | ✅ |

Expand Down Expand Up @@ -91,7 +103,7 @@ small, well-tested key-verification step.
> bundled into unrelated work.

### 3. MCP — add HTTP transport (Phase 2)
- Extend `plugin-mcp-server` with a **streamable-http** (with SSE fallback) transport mounted at a stable route (`/api/v1/mcp`), gated by `OS_MCP_SERVER_ENABLED` per env (explicit opt-in — exposing tools is a deliberate act).
- Extend `@objectstack/mcp` with a **streamable-http** (with SSE fallback) transport mounted at a stable route (`/api/v1/mcp`), gated by `OS_MCP_SERVER_ENABLED` per env (explicit opt-in — exposing tools is a deliberate act).
- Auth: the same `sys_api_key` Bearer; the advertised `tools` are the env's object CRUD + any AI tools the key is scoped for.
- The Integrations page **generates the connection config** (Claude Desktop `claude_desktop_config.json` / Cursor snippet) with the env's MCP URL + a generated key, and a one-click copy/download.

Expand Down Expand Up @@ -125,4 +137,7 @@ small, well-tested key-verification step.
- **Security**: every external entry runs as a scoped `sys_api_key` principal under existing object permissions + RLS; MCP is opt-in per env; keys are revocable.

## Status / next
Phase 1 (Integrations page + API-key UX + publish-success link) is implementable now against shipped endpoints. Phase 2 (MCP HTTP transport) follows as a framework change with its own tests.
- **Phase 1a (framework auth) — shipped** (#1624): `sys_api_key` Bearer/header verified on the runtime auth path → principal under existing permissions + RLS.
- **Phase 1b (objectui surfacing)** — Integrations page + show-once key + publish "View API" link.
- **Phase 2 (framework MCP HTTP transport) — shipped** (#1626; package since renamed to `@objectstack/mcp`): Streamable HTTP at `/api/v1/mcp`, opt-in `OS_MCP_SERVER_ENABLED`, fail-closed auth, principal-bound object-CRUD tools.
- **Phase 2b (surfacing, per Amendment C)** — env-level remote-MCP connect (URL + show-once key + one-click deeplink) and a single generic ObjectStack **Skill**; *not* per-app, *not* hand-maintained vendor snippets.
2 changes: 1 addition & 1 deletion packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
"@objectstack/plugin-auth": "workspace:*",
"@objectstack/plugin-email": "workspace:*",
"@objectstack/plugin-hono-server": "workspace:*",
"@objectstack/plugin-mcp-server": "workspace:*",
"@objectstack/mcp": "workspace:*",
"@objectstack/plugin-org-scoping": "workspace:*",
"@objectstack/plugin-reports": "workspace:*",
"@objectstack/plugin-security": "workspace:*",
Expand Down
4 changes: 2 additions & 2 deletions packages/cli/src/commands/serve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1505,9 +1505,9 @@ export default class Serve extends Command {
nameMatch: ['service-feed', 'FeedServicePlugin'],
},
mcp: {
pkg: '@objectstack/plugin-mcp-server',
pkg: '@objectstack/mcp',
export: 'MCPServerPlugin',
nameMatch: ['mcp-server', 'MCPServerPlugin'],
nameMatch: ['mcp-server', 'MCPServerPlugin', 'mcp'],
},
marketplace: {
pkg: '@objectstack/service-package',
Expand Down
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# @objectstack/plugin-mcp-server
# @objectstack/mcp

MCP Runtime Server Plugin for ObjectStack — exposes AI tools, data resources, and agent prompts via the Model Context Protocol.

Expand Down Expand Up @@ -26,18 +26,18 @@ Read more: [MCP Specification](https://modelcontextprotocol.io/)
## Installation

```bash
pnpm add @objectstack/plugin-mcp-server
pnpm add @objectstack/mcp
```

## Basic Usage

```typescript
import { defineStack } from '@objectstack/spec';
import { PluginMCPServer } from '@objectstack/plugin-mcp-server';
import { MCPServerPlugin } from '@objectstack/mcp';

const stack = defineStack({
plugins: [
PluginMCPServer.configure({
MCPServerPlugin.configure({
serverName: 'objectstack-server',
version: '1.0.0',
autoRegisterTools: true,
Expand Down Expand Up @@ -296,7 +296,7 @@ Configure in Cline settings:
```typescript
// server.ts
import { defineStack } from '@objectstack/spec';
import { PluginMCPServer } from '@objectstack/plugin-mcp-server';
import { MCPServerPlugin } from '@objectstack/mcp';
import { DriverSql } from '@objectstack/driver-sql';

const stack = defineStack({
Expand All @@ -305,7 +305,7 @@ const stack = defineStack({
connection: { filename: process.env.DATABASE_URL ?? './data/app.db' },
}),
plugins: [
PluginMCPServer.configure({
MCPServerPlugin.configure({
serverName: 'my-crm',
transport: 'stdio', // Claude Desktop, Cursor, Cline
}),
Expand All @@ -321,7 +321,7 @@ await stack.boot();
const stack = defineStack({
driver: DriverSql.configure({ /* ... */ }),
plugins: [
PluginMCPServer.configure({
MCPServerPlugin.configure({
serverName: 'my-crm',
transport: 'http',
port: 3100,
Expand Down Expand Up @@ -457,7 +457,7 @@ The MCP server exposes these capabilities:
Enable debug logging:

```typescript
PluginMCPServer.configure({
MCPServerPlugin.configure({
serverName: 'my-crm',
debug: true, // Log all MCP messages
});
Expand All @@ -472,12 +472,12 @@ View MCP messages in client:

```typescript
import { defineStack, defineTool } from '@objectstack/spec';
import { PluginMCPServer } from '@objectstack/plugin-mcp-server';
import { MCPServerPlugin } from '@objectstack/mcp';

const stack = defineStack({
driver: /* ... */,
plugins: [
PluginMCPServer.configure({
MCPServerPlugin.configure({
serverName: 'crm-assistant',
autoRegisterTools: true,
}),
Expand Down Expand Up @@ -518,7 +518,7 @@ mcp.registerPrompt({

## License

Apache-2.0. See [LICENSING.md](../../../LICENSING.md).
Apache-2.0. See [LICENSING.md](../../LICENSING.md).

## See Also

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"name": "@objectstack/plugin-mcp-server",
"name": "@objectstack/mcp",
"version": "7.9.0",
"license": "Apache-2.0",
"description": "MCP Runtime Server Plugin for ObjectStack — exposes AI tools, data resources, and agent prompts via the Model Context Protocol",
"description": "ObjectStack as an MCP server — exposes your app's objects (and AI tools) over the Model Context Protocol (stdio + Streamable HTTP)",
"type": "module",
"main": "dist/index.js",
"types": "dist/index.d.ts",
Expand All @@ -14,7 +14,7 @@
}
},
"scripts": {
"build": "tsup --config ../../../tsup.config.ts",
"build": "tsup --config ../../tsup.config.ts",
"test": "vitest run"
},
"dependencies": {
Expand All @@ -41,7 +41,7 @@
"repository": {
"type": "git",
"url": "https://github.com/objectstack-ai/framework.git",
"directory": "packages/plugins/plugin-mcp-server"
"directory": "packages/mcp"
},
"homepage": "https://objectstack.ai/docs",
"bugs": "https://github.com/objectstack-ai/framework/issues",
Expand Down
Loading
Loading