Skip to content

@objectstack/mcp@16.0.0

Choose a tag to compare

@github-actions github-actions released this 21 Jul 06:25
f55be04

Minor Changes

  • 15dbe18: feat(mcp)!: stdio transport requires an API-key principal — fail-closed, no unscoped bridge (ADR-0101, #3246)

    The long-lived MCP stdio transport no longer reads data unscoped. It now runs
    under an env-supplied identity, closing the platform's last identity-less
    execution surface (the mcp-stdio-authority conformance row graduates
    experimentalenforced).

    • OS_MCP_STDIO_API_KEY=osk_... supplies the stdio identity, resolved through
      the SAME @objectstack/core verify + authorization chain as the HTTP/REST
      surfaces; the record_by_id resource reads via ql.find(obj, { where:{id}, context }), so RLS/FLS/tenant apply exactly as on REST /data. Re-resolved
      per read, so a revoked/expired key stops working on a live session.
    • Fail-closed — enabling stdio auto-start (OS_MCP_STDIO_ENABLED=true /
      autoStart) without a resolvable key throws and refuses to start. There is no
      unscoped fallback and deliberately no system bypass; full authority is a key
      minted on a platform-admin or dedicated service identity.

    BREAKING (stdio auto-start only): previously OS_MCP_STDIO_ENABLED=true
    (or the plugin autoStart option) started stdio with full, unscoped authority
    and no credential. It now requires OS_MCP_STDIO_API_KEY; without it, boot
    fails closed. The default-on HTTP surface and any deployment that never enables
    stdio auto-start are unaffected.

  • 83e8f7d: feat(mcp): decouple the stdio auto-start switch from the HTTP surface + surface the MCP endpoint on os dev boot (#3167)

    The MCP HTTP surface (/api/v1/mcp) and the long-lived stdio transport used to
    share one env var: OS_MCP_SERVER_ENABLED=true turned the HTTP surface on and
    silently auto-started the stdio transport — which bridges the raw metadata service

    • data engine with no per-request principal (unscoped). An operator setting it to
      "make sure MCP is on" got an unscoped transport as a side effect.
    • @objectstack/types — new resolveMcpStdioAutoStart(). Stdio auto-start is
      now its own switch, OS_MCP_STDIO_ENABLED (default off); OS_MCP_SERVER_ENABLED
      governs only the HTTP surface. The legacy OS_MCP_SERVER_ENABLED=true trigger
      still starts stdio for one release, flagged as deprecated. =false is unchanged
      (it only ever gated HTTP).
    • @objectstack/mcpMCPServerPlugin.start() gates stdio on the new switch
      and logs a one-time deprecation warning when started via the legacy alias.
    • @objectstack/clios dev now prints the MCP endpoint, the agent-skill
      URL, and a ready-to-paste claude mcp add command on boot (gated on the HTTP
      surface being on), so the "an agent operates the app it's building" loop is
      discoverable at dev time.
    • create-objectstack — the blank scaffold README documents that the app is
      itself an MCP server (the serve side), distinct from the consume-side connector.
  • 230358c: feat(mcp): validate_expression tool — validate a CEL expression against a schema before authoring (#1928)

    Adds an agent-callable MCP tool that runs the same build-time expression checks
    as objectstack build, so an AI can validate a formula / predicate / flow
    condition while authoring instead of shipping one that silently evaluates to
    null. Given { objectName, expression, site? } it resolves the object's real
    schema (field names + types, via the principal-bound describeObject bridge)
    and returns:

    • errors — bare field refs (amountrecord.amount), unknown fields
      (with a did-you-mean), unknown functions;
    • warnings — text/boolean fields misused in arithmetic, date-equality
      pitfalls;
    • inScope — the fields, stdlib functions, and namespace roots available, so
      the model can self-correct;
    • inferredType for a formula site.

    site (formula | validation | flow_condition | template, default
    formula) maps to the validator's role + scope — flow_condition binds fields
    bare, the rest bind record.<field>. Read-only, gated by the data:read OAuth
    scope, and fail-closed on sys_* objects like the other schema tools. This is
    the authoring-time surface the guardrail series (#1928) always pointed at;
    @objectstack/mcp gains a @objectstack/formula dependency (acyclic; formula is
    a leaf).

Patch Changes