From 13072240b1e16d0a450635ba9f381b02443ce06b Mon Sep 17 00:00:00 2001 From: Jack Zhuang <277994282+os-zhuang@users.noreply.github.com> Date: Sun, 7 Jun 2026 06:03:04 +0800 Subject: [PATCH] =?UTF-8?q?refactor(mcp)!:=20rename=20@objectstack/plugin-?= =?UTF-8?q?mcp-server=20=E2=86=92=20@objectstack/mcp=20+=20ADR-0036=20amen?= =?UTF-8?q?dment?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Drops the legacy `plugin-` prefix and moves the outbound MCP-server package to the top level (`packages/mcp`), parallel to `@objectstack/rest` — both are "your app exposed over a protocol". Inbound MCP stays `@objectstack/connector-mcp`. - packages/plugins/plugin-mcp-server → packages/mcp; name → @objectstack/mcp; internal plugin id → com.objectstack.mcp; build/tsconfig relative paths fixed for the new depth. Exported API unchanged (MCPServerPlugin, MCPServerRuntime, registerObjectTools, McpDataBridge, …). - @objectstack/cli: dependency + dynamic-loader pkg id updated. - Inbound refs (runtime test, spec comment, changeset config, docs) updated. Pre-launch clean break — no compat shim (only cli depended on it internally). - ADR-0036 amendment (2026-06-07): records (A) the rename, (B) granularity = per-environment not per-app (one MCP server per env covers all apps; dynamic apps via live discovery; key-scope for narrowing), (C) distribution = skills + MCP (one generic portable Skill + live MCP, not hand-maintained vendor config snippets) — verified Agent Skills is now an open cross-platform standard. - Status updated: Phase 1a (#1624) + Phase 2 (#1626) shipped; Phase 2b next. Build + typecheck + tests green (mcp 36, runtime mcp 5); lockfile regenerated. Co-Authored-By: Claude Opus 4.8 --- .changeset/config.json | 2 +- .changeset/mcp-streamable-http-transport.md | 4 +- .changeset/rename-mcp-package.md | 18 +++++ README.md | 2 +- RELEASE_NOTES.md | 2 +- content/docs/guides/packages.mdx | 6 +- content/docs/references/ai/mcp.mdx | 2 +- .../0036-app-as-rest-api-and-mcp-server.md | 27 +++++-- packages/cli/package.json | 2 +- packages/cli/src/commands/serve.ts | 4 +- .../plugin-mcp-server => mcp}/CHANGELOG.md | 0 .../plugin-mcp-server => mcp}/LICENSE | 0 .../plugin-mcp-server => mcp}/README.md | 22 +++--- .../plugin-mcp-server => mcp}/package.json | 8 +-- .../src/__tests__/mcp-server-runtime.test.ts | 0 .../src/__tests__/plugin.test.ts | 2 +- .../plugin-mcp-server => mcp}/src/index.ts | 11 +-- .../src/mcp-http-tools.ts | 0 .../src/mcp-server-runtime.http.test.ts | 0 .../src/mcp-server-runtime.ts | 0 .../plugin-mcp-server => mcp}/src/plugin.ts | 4 +- .../plugin-mcp-server => mcp}/src/types.ts | 0 .../plugin-mcp-server => mcp}/tsconfig.json | 2 +- .../runtime/src/http-dispatcher.mcp.test.ts | 2 +- packages/spec/src/ai/mcp.zod.ts | 2 +- pnpm-lock.yaml | 72 +++++++++---------- 26 files changed, 111 insertions(+), 83 deletions(-) create mode 100644 .changeset/rename-mcp-package.md rename packages/{plugins/plugin-mcp-server => mcp}/CHANGELOG.md (100%) rename packages/{plugins/plugin-mcp-server => mcp}/LICENSE (100%) rename packages/{plugins/plugin-mcp-server => mcp}/README.md (96%) rename packages/{plugins/plugin-mcp-server => mcp}/package.json (78%) rename packages/{plugins/plugin-mcp-server => mcp}/src/__tests__/mcp-server-runtime.test.ts (100%) rename packages/{plugins/plugin-mcp-server => mcp}/src/__tests__/plugin.test.ts (99%) rename packages/{plugins/plugin-mcp-server => mcp}/src/index.ts (57%) rename packages/{plugins/plugin-mcp-server => mcp}/src/mcp-http-tools.ts (100%) rename packages/{plugins/plugin-mcp-server => mcp}/src/mcp-server-runtime.http.test.ts (100%) rename packages/{plugins/plugin-mcp-server => mcp}/src/mcp-server-runtime.ts (100%) rename packages/{plugins/plugin-mcp-server => mcp}/src/plugin.ts (97%) rename packages/{plugins/plugin-mcp-server => mcp}/src/types.ts (100%) rename packages/{plugins/plugin-mcp-server => mcp}/tsconfig.json (84%) diff --git a/.changeset/config.json b/.changeset/config.json index 4326f1a13..1aa079b5a 100644 --- a/.changeset/config.json +++ b/.changeset/config.json @@ -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", diff --git a/.changeset/mcp-streamable-http-transport.md b/.changeset/mcp-streamable-http-transport.md index 121cfae43..4f1468fe0 100644 --- a/.changeset/mcp-streamable-http-transport.md +++ b/.changeset/mcp-streamable-http-transport.md @@ -1,5 +1,5 @@ --- -'@objectstack/plugin-mcp-server': minor +'@objectstack/mcp': minor '@objectstack/runtime': minor --- @@ -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 diff --git a/.changeset/rename-mcp-package.md b/.changeset/rename-mcp-package.md new file mode 100644 index 000000000..35542d928 --- /dev/null +++ b/.changeset/rename-mcp-package.md @@ -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). diff --git a/README.md b/README.md index ba967956e..141ee3d50 100644 --- a/README.md +++ b/README.md @@ -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 | diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index f1bbaceee..6fcea496f 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -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 diff --git a/content/docs/guides/packages.mdx b/content/docs/guides/packages.mdx index d6798ec55..e6c887a5f 100644 --- a/content/docs/guides/packages.mdx +++ b/content/docs/guides/packages.mdx @@ -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` | @@ -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 diff --git a/content/docs/references/ai/mcp.mdx b/content/docs/references/ai/mcp.mdx index 2746646bf..65d07542a 100644 --- a/content/docs/references/ai/mcp.mdx +++ b/content/docs/references/ai/mcp.mdx @@ -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: diff --git a/docs/adr/0036-app-as-rest-api-and-mcp-server.md b/docs/adr/0036-app-as-rest-api-and-mcp-server.md index 9d7e7f796..4c09372eb 100644 --- a/docs/adr/0036-app-as-rest-api-and-mcp-server.md +++ b/docs/adr/0036-app-as-rest-api-and-mcp-server.md @@ -3,7 +3,7 @@ **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. @@ -11,15 +11,27 @@ --- +## 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 (`/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. @@ -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 (`.objectos.app`) = API/MCP base | cloud env registry | ✅ | @@ -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. @@ -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. diff --git a/packages/cli/package.json b/packages/cli/package.json index 22980aa3f..6fd03dcb9 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -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:*", diff --git a/packages/cli/src/commands/serve.ts b/packages/cli/src/commands/serve.ts index 7a75c97d8..208130f9e 100644 --- a/packages/cli/src/commands/serve.ts +++ b/packages/cli/src/commands/serve.ts @@ -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', diff --git a/packages/plugins/plugin-mcp-server/CHANGELOG.md b/packages/mcp/CHANGELOG.md similarity index 100% rename from packages/plugins/plugin-mcp-server/CHANGELOG.md rename to packages/mcp/CHANGELOG.md diff --git a/packages/plugins/plugin-mcp-server/LICENSE b/packages/mcp/LICENSE similarity index 100% rename from packages/plugins/plugin-mcp-server/LICENSE rename to packages/mcp/LICENSE diff --git a/packages/plugins/plugin-mcp-server/README.md b/packages/mcp/README.md similarity index 96% rename from packages/plugins/plugin-mcp-server/README.md rename to packages/mcp/README.md index 06c2a7983..63606dc6d 100644 --- a/packages/plugins/plugin-mcp-server/README.md +++ b/packages/mcp/README.md @@ -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. @@ -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, @@ -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({ @@ -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 }), @@ -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, @@ -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 }); @@ -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, }), @@ -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 diff --git a/packages/plugins/plugin-mcp-server/package.json b/packages/mcp/package.json similarity index 78% rename from packages/plugins/plugin-mcp-server/package.json rename to packages/mcp/package.json index 4446086a2..a5fd6dd7a 100644 --- a/packages/plugins/plugin-mcp-server/package.json +++ b/packages/mcp/package.json @@ -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", @@ -14,7 +14,7 @@ } }, "scripts": { - "build": "tsup --config ../../../tsup.config.ts", + "build": "tsup --config ../../tsup.config.ts", "test": "vitest run" }, "dependencies": { @@ -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", diff --git a/packages/plugins/plugin-mcp-server/src/__tests__/mcp-server-runtime.test.ts b/packages/mcp/src/__tests__/mcp-server-runtime.test.ts similarity index 100% rename from packages/plugins/plugin-mcp-server/src/__tests__/mcp-server-runtime.test.ts rename to packages/mcp/src/__tests__/mcp-server-runtime.test.ts diff --git a/packages/plugins/plugin-mcp-server/src/__tests__/plugin.test.ts b/packages/mcp/src/__tests__/plugin.test.ts similarity index 99% rename from packages/plugins/plugin-mcp-server/src/__tests__/plugin.test.ts rename to packages/mcp/src/__tests__/plugin.test.ts index f9dc40702..c35ec5eb4 100644 --- a/packages/plugins/plugin-mcp-server/src/__tests__/plugin.test.ts +++ b/packages/mcp/src/__tests__/plugin.test.ts @@ -96,7 +96,7 @@ describe('MCPServerPlugin', () => { describe('metadata', () => { it('should have correct plugin metadata', () => { const plugin = new MCPServerPlugin(); - expect(plugin.name).toBe('com.objectstack.plugin-mcp-server'); + expect(plugin.name).toBe('com.objectstack.mcp'); expect(plugin.version).toBe('1.0.0'); expect(plugin.type).toBe('standard'); }); diff --git a/packages/plugins/plugin-mcp-server/src/index.ts b/packages/mcp/src/index.ts similarity index 57% rename from packages/plugins/plugin-mcp-server/src/index.ts rename to packages/mcp/src/index.ts index a669774e2..a52d71e87 100644 --- a/packages/plugins/plugin-mcp-server/src/index.ts +++ b/packages/mcp/src/index.ts @@ -1,12 +1,13 @@ // Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license. /** - * @objectstack/plugin-mcp-server + * @objectstack/mcp * - * MCP Runtime Server Plugin for ObjectStack. - * Exposes all registered AI tools, data resources, and agent prompts - * via the Model Context Protocol (MCP) for use by external AI clients - * (Claude Desktop, Cursor, VS Code Copilot, etc.). + * ObjectStack as an MCP server. Exposes your app's objects (and registered AI + * tools, data resources, agent prompts) over the Model Context Protocol — via + * stdio (local) and Streamable HTTP (remote agents: Claude, Cursor, Codex, + * Gemini, Copilot, …). The inbound sibling (consuming external MCP servers) is + * `@objectstack/connector-mcp`. */ export { MCPServerPlugin } from './plugin.js'; diff --git a/packages/plugins/plugin-mcp-server/src/mcp-http-tools.ts b/packages/mcp/src/mcp-http-tools.ts similarity index 100% rename from packages/plugins/plugin-mcp-server/src/mcp-http-tools.ts rename to packages/mcp/src/mcp-http-tools.ts diff --git a/packages/plugins/plugin-mcp-server/src/mcp-server-runtime.http.test.ts b/packages/mcp/src/mcp-server-runtime.http.test.ts similarity index 100% rename from packages/plugins/plugin-mcp-server/src/mcp-server-runtime.http.test.ts rename to packages/mcp/src/mcp-server-runtime.http.test.ts diff --git a/packages/plugins/plugin-mcp-server/src/mcp-server-runtime.ts b/packages/mcp/src/mcp-server-runtime.ts similarity index 100% rename from packages/plugins/plugin-mcp-server/src/mcp-server-runtime.ts rename to packages/mcp/src/mcp-server-runtime.ts diff --git a/packages/plugins/plugin-mcp-server/src/plugin.ts b/packages/mcp/src/plugin.ts similarity index 97% rename from packages/plugins/plugin-mcp-server/src/plugin.ts rename to packages/mcp/src/plugin.ts index c8c5e1b3b..6ce30dca0 100644 --- a/packages/plugins/plugin-mcp-server/src/plugin.ts +++ b/packages/mcp/src/plugin.ts @@ -42,7 +42,7 @@ export interface MCPServerPluginOptions { * @example * ```ts * import { LiteKernel } from '@objectstack/core'; - * import { MCPServerPlugin } from '@objectstack/plugin-mcp-server'; + * import { MCPServerPlugin } from '@objectstack/mcp'; * * const kernel = new LiteKernel(); * kernel.use(new MCPServerPlugin({ autoStart: true })); @@ -50,7 +50,7 @@ export interface MCPServerPluginOptions { * ``` */ export class MCPServerPlugin implements Plugin { - name = 'com.objectstack.plugin-mcp-server'; + name = 'com.objectstack.mcp'; version = '1.0.0'; type = 'standard' as const; dependencies: string[] = []; diff --git a/packages/plugins/plugin-mcp-server/src/types.ts b/packages/mcp/src/types.ts similarity index 100% rename from packages/plugins/plugin-mcp-server/src/types.ts rename to packages/mcp/src/types.ts diff --git a/packages/plugins/plugin-mcp-server/tsconfig.json b/packages/mcp/tsconfig.json similarity index 84% rename from packages/plugins/plugin-mcp-server/tsconfig.json rename to packages/mcp/tsconfig.json index f6a1e8bad..39c4b5a15 100644 --- a/packages/plugins/plugin-mcp-server/tsconfig.json +++ b/packages/mcp/tsconfig.json @@ -1,5 +1,5 @@ { - "extends": "../../../tsconfig.json", + "extends": "../../tsconfig.json", "compilerOptions": { "outDir": "./dist", "rootDir": "./src", diff --git a/packages/runtime/src/http-dispatcher.mcp.test.ts b/packages/runtime/src/http-dispatcher.mcp.test.ts index f87e2cf19..c16550d7f 100644 --- a/packages/runtime/src/http-dispatcher.mcp.test.ts +++ b/packages/runtime/src/http-dispatcher.mcp.test.ts @@ -7,7 +7,7 @@ import { HttpDispatcher } from './http-dispatcher.js'; /** * These tests drive `handleMcp` directly to verify the gate + auth + bridge * wiring without standing up a full kernel. The MCP transport itself is tested - * in @objectstack/plugin-mcp-server; here we assert: + * in @objectstack/mcp; here we assert: * - opt-in gate (OS_MCP_SERVER_ENABLED) * - fail-closed auth (anonymous → 401) * - the injected bridge runs through callData bound to the request's diff --git a/packages/spec/src/ai/mcp.zod.ts b/packages/spec/src/ai/mcp.zod.ts index a1fded6c0..48a8acdc3 100644 --- a/packages/spec/src/ai/mcp.zod.ts +++ b/packages/spec/src/ai/mcp.zod.ts @@ -9,7 +9,7 @@ import { lazySchema } from '../shared/lazy-schema'; * MCP itself is an external protocol defined by Anthropic * (https://modelcontextprotocol.io). The platform does NOT re-define * 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 `@objectstack/mcp`. * * This file defines only the two things the *platform* needs: * diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9894a3d8f..ca08d10e8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -479,6 +479,9 @@ importers: '@objectstack/formula': specifier: workspace:* version: link:../formula + '@objectstack/mcp': + specifier: workspace:* + version: link:../mcp '@objectstack/objectql': specifier: workspace:^ version: link:../objectql @@ -503,9 +506,6 @@ importers: '@objectstack/plugin-hono-server': specifier: workspace:* version: link:../plugins/plugin-hono-server - '@objectstack/plugin-mcp-server': - specifier: workspace:* - version: link:../plugins/plugin-mcp-server '@objectstack/plugin-org-scoping': specifier: workspace:* version: link:../plugins/plugin-org-scoping @@ -843,6 +843,34 @@ importers: specifier: ^4.1.8 version: 4.1.8(@opentelemetry/api@1.9.1)(@types/node@25.9.1)(@vitest/coverage-v8@4.1.8)(happy-dom@20.9.0)(msw@2.14.6(@types/node@25.9.1)(typescript@6.0.3))(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) + packages/mcp: + dependencies: + '@modelcontextprotocol/sdk': + specifier: ^1.29.0 + version: 1.29.0(zod@4.4.3) + '@objectstack/core': + specifier: workspace:* + version: link:../core + '@objectstack/spec': + specifier: workspace:* + version: link:../spec + '@objectstack/types': + specifier: workspace:* + version: link:../types + zod: + specifier: ^4.4.3 + version: 4.4.3 + devDependencies: + '@types/node': + specifier: ^25.9.1 + version: 25.9.1 + typescript: + specifier: ^6.0.3 + version: 6.0.3 + vitest: + specifier: ^4.1.8 + version: 4.1.8(@opentelemetry/api@1.9.1)(@types/node@25.9.1)(@vitest/coverage-v8@4.1.8)(happy-dom@20.9.0)(msw@2.14.6(@types/node@25.9.1)(typescript@6.0.3))(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) + packages/metadata: dependencies: '@objectstack/core': @@ -1379,34 +1407,6 @@ importers: specifier: ^4.1.8 version: 4.1.8(@opentelemetry/api@1.9.1)(@types/node@25.9.1)(@vitest/coverage-v8@4.1.8)(happy-dom@20.9.0)(msw@2.14.6(@types/node@25.9.1)(typescript@6.0.3))(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) - packages/plugins/plugin-mcp-server: - dependencies: - '@modelcontextprotocol/sdk': - specifier: ^1.29.0 - version: 1.29.0(zod@4.4.3) - '@objectstack/core': - specifier: workspace:* - version: link:../../core - '@objectstack/spec': - specifier: workspace:* - version: link:../../spec - '@objectstack/types': - specifier: workspace:* - version: link:../../types - zod: - specifier: ^4.4.3 - version: 4.4.3 - devDependencies: - '@types/node': - specifier: ^25.9.1 - version: 25.9.1 - typescript: - specifier: ^6.0.3 - version: 6.0.3 - vitest: - specifier: ^4.1.8 - version: 4.1.8(@opentelemetry/api@1.9.1)(@types/node@25.9.1)(@vitest/coverage-v8@4.1.8)(happy-dom@20.9.0)(msw@2.14.6(@types/node@25.9.1)(typescript@6.0.3))(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) - packages/plugins/plugin-msw: dependencies: '@objectstack/core': @@ -5811,10 +5811,6 @@ packages: resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} engines: {node: '>=0.8.x'} - eventsource-parser@3.0.8: - resolution: {integrity: sha512-70QWGkr4snxr0OXLRWsFLeRBIRPuQOvt4s8QYjmUlmlkyTZkRqS7EDVRZtzU3TiyDbXSzaOeF0XUKy8PchzukQ==} - engines: {node: '>=18.0.0'} - eventsource-parser@3.1.0: resolution: {integrity: sha512-kJezFj9YFAMLeORyi7aCLxLbD5/qWMQnoMVlVPyHIll7lgRJCc3JVln9Vgl9nwQi0YkMnhdGTMNn7CkRRAptMg==} engines: {node: '>=18.0.0'} @@ -10211,7 +10207,7 @@ snapshots: cors: 2.8.6 cross-spawn: 7.0.6 eventsource: 3.0.7 - eventsource-parser: 3.0.8 + eventsource-parser: 3.1.0 express: 5.2.1 express-rate-limit: 8.5.2(express@5.2.1) hono: 4.12.23 @@ -12707,13 +12703,11 @@ snapshots: events@3.3.0: {} - eventsource-parser@3.0.8: {} - eventsource-parser@3.1.0: {} eventsource@3.0.7: dependencies: - eventsource-parser: 3.0.8 + eventsource-parser: 3.1.0 expand-template@2.0.3: {}