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
9 changes: 7 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,13 @@ All notable changes to this project will be documented in this file. The format

### Added

- [#377](https://github.com/mohanagy/miftah/issues/377) Added the opt-in production profile-context boundary for trusted modern stateless hosts. Short-lived authenticated-encrypted handles bind a named profile to the verified issuer, subject, audience, chat, deployment, and monotonic sealing-key epoch; deployment-wide revocation, exact expiry, removed-profile checks, bearer-free keyed audit correlation, audited rejection and replacement-before-revocation ordering, and fixed fail-closed errors apply on every request. Reserved tool or request metadata is stripped before audit argument capture and upstream forwarding, transition approvals are bound to the authenticated chat correlation, modern discovery enforces identical client-visible tools across profiles and is independent of prior selection calls, and existing stdio plus CLI-owned session-aware HTTP behavior remains unchanged until protocol-era negotiation is enabled separately.
- [#376](https://github.com/mohanagy/miftah/issues/376) Added a public authenticated request-context boundary for future modern stateless handling. Trusted embedding hosts can provide verified issuer, subject, audience, per-chat, issuance, and expiry claims; Miftah derives only opaque deployment-bound and separately keyed audit correlations, fails closed on missing, malformed, expired, or mismatched context, and never falls back to MCP `clientInfo`, arbitrary headers, request metadata, tool arguments, or mutable profile state. The existing CLI-owned Streamable HTTP server remains the legacy session-aware path until a supported host supplies the trusted per-chat claim and modern protocol integration is enabled.
- [#363](https://github.com/mohanagy/miftah/issues/363) Added MCP `2026-07-28` serving alongside the existing legacy initialized era. STDIO now negotiates both eras through the SDK v2 serving entry; Streamable HTTP classifies each request before routing it to a fresh request-scoped modern server or the existing bounded sessionful legacy host. Modern requests use `server/discover`, carry per-request metadata, omit `Mcp-Session-Id`, propagate cancellation to the selected upstream, and return explicit supported-version diagnostics. The new public `createMiftahServerFactory` lets a trusted embedding host attach the authenticated stateless profile-context boundary without exposing Miftah's broker, policy, audit, OAuth, routing, or lifecycle internals.
- [#377](https://github.com/mohanagy/miftah/issues/377) Added the opt-in production profile-context boundary for trusted modern stateless hosts. Short-lived authenticated-encrypted handles bind a named profile to the verified issuer, subject, audience, chat, deployment, and monotonic sealing-key epoch; deployment-wide revocation, exact expiry, removed-profile checks, bearer-free keyed audit correlation, audited rejection and replacement-before-revocation ordering, and fixed fail-closed errors apply on every request. Reserved tool or request metadata is stripped before audit argument capture and upstream forwarding, transition approvals are bound to the authenticated chat correlation, and modern discovery enforces identical client-visible tools across profiles and is independent of prior selection calls. The CLI host does not synthesize trusted chat claims; an embedding host enables the boundary through `createMiftahServerFactory`.
- [#376](https://github.com/mohanagy/miftah/issues/376) Added a public authenticated request-context boundary for modern stateless handling. Trusted embedding hosts can provide verified issuer, subject, audience, per-chat, issuance, and expiry claims; Miftah derives only opaque deployment-bound and separately keyed audit correlations, fails closed on missing, malformed, expired, or mismatched context, and never falls back to MCP `clientInfo`, arbitrary headers, request metadata, tool arguments, or mutable profile state. The CLI-owned Streamable HTTP server negotiates the modern protocol without inventing these trusted claims; embedding hosts supply them through the public server factory.

### Changed

- [#363](https://github.com/mohanagy/miftah/issues/363) Replaced the monolithic MCP TypeScript SDK v1 dependency with the stable v2 split packages and migrated runtime schemas to Zod 4. Runtime consumers receive only `client`, `core`, and `server`; the Node adapter and frozen legacy server remain build/test dependencies. Direct consumers of the old monolithic SDK deep imports must move to the corresponding split package. The CLI bundles the v2 Node adapter with patched `@hono/node-server` and Hono builds so a fresh Miftah install does not inherit the Node package's still-vulnerable 1.x adapter range; custom embedding hosts own their direct Node adapter version. Confirmation-required tools, resources, prompts, and profile transitions now use the v2 `input_required` flow with integrity-bound one-time continuation state across request-scoped modern HTTP instances, while the SDK legacy shim preserves form elicitation for initialized clients. Native OAuth callback completion now carries the authorization-server issuer required by the v2 provider contract; Miftah continues to validate and round-trip that issuer without exposing tokens or client secrets.

## [1.0.0] - 2026-08-11

Expand Down
35 changes: 27 additions & 8 deletions docs/library-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
| `MIFTAH_VERSION` | The package version compiled into Miftah's CLI and MCP metadata. |
| `CURRENT_CONFIG_VERSION` | The canonical configuration format written by current Miftah presets and examples. |
| `createMiftahRuntime` | Creates an MCP wrapper from a configuration file without exposing process, profile, or server internals. |
| `createMiftahServerFactory` | Creates fresh lifecycle-managed MCP server instances for the SDK v2 serving entries. |
| `ProfileContextHandleService` | Mints, resolves, replaces, and revokes short-lived opaque profile selectors for a trusted modern stateless host. |
| `ProfileContextHandleError` | Fixed-code error class that never includes a handle, decrypted payload, identity claim, or backend detail. |
| `InMemoryProfileContextRevocationStore` | Bounded same-process implementation for tests and single-process hosts; it is not deployment-wide storage. |
Expand All @@ -23,16 +24,34 @@
| `generateConfigSchema` | Generates the editor-facing JSON Schema for the configuration contract. |
| `presetConfig` | Creates a supported configuration preset in memory. |

`createMiftahRuntime` returns `MiftahRuntime`, which exposes the resolved `config`, `connect(transport)`, and `close()` methods. Its optional `MiftahRuntimeOptions` enables the modern profile-context boundary described below. Supply an MCP SDK transport such as `StdioServerTransport`; transport types are provided by the direct `@modelcontextprotocol/sdk` dependency.
`createMiftahRuntime` returns `MiftahRuntime`, which exposes the resolved `config`, `connect(transport)`, and `close()` methods for hosts that own a specific transport lifecycle. `createMiftahServerFactory` is the preferred boundary for the SDK v2 serving entries because every factory invocation creates a fresh prepared Miftah server whose upstreams close with that server. Both functions accept `MiftahRuntimeOptions`, including the modern profile-context boundary described below. The removed monolithic `@modelcontextprotocol/sdk` package is not part of the supported dependency surface. Miftah's CLI bundles the v2 Node adapter with its patched Hono adapter because `@modelcontextprotocol/node@2.0.0` still advertises an unsafe 1.x adapter range; embedding hosts import and version their own `@modelcontextprotocol/node` package when adapting a custom Node HTTP server.

```ts
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { createMiftahRuntime } from "@lubab/miftah";
import { serveStdio } from "@modelcontextprotocol/server/stdio";
import { createMiftahServerFactory } from "@lubab/miftah";

const runtime = await createMiftahRuntime("./miftah.json");
await runtime.connect(new StdioServerTransport());
const server = serveStdio(createMiftahServerFactory("./miftah.json"));

// Later, during host shutdown:
await server.close();
```

For a custom HTTP host, pass the same factory to `createMcpHandler` from `@modelcontextprotocol/server` and adapt the web handler with `toNodeHandler` from `@modelcontextprotocol/node` when using Node's HTTP server.

## MCP protocol compatibility matrix

| Transport and era | Serving path | Lifecycle and compatibility |
| --- | --- | --- |
| STDIO, modern `2026-07-28` | CLI `miftah serve` or SDK v2 `serveStdio(createMiftahServerFactory(...))` | Negotiates with `server/discover`; there is no `initialize`/`initialized` handshake or session identifier. |
| STDIO, legacy 2025-era | The same STDIO entry | Preserves the SDK-managed `initialize`/`initialized` path. Interop tests negotiate the SDK v2 preferred legacy revision, `2025-11-25`. |
| Streamable HTTP, modern `2026-07-28` | CLI-owned `/mcp` endpoint or an embedding host's `createMcpHandler` | Creates one server per request, emits no `Mcp-Session-Id`, carries request metadata through the SDK v2 context, and propagates request cancellation upstream. |
| Streamable HTTP, legacy 2025-era | CLI-owned `/mcp` endpoint | Preserves the existing sessionful path, including `initialize`/`initialized`, `Mcp-Session-Id`, idle expiry, and bounded session admission. |
| Unsupported pinned modern revision | Modern HTTP or STDIO serving entry | Fails with a version-negotiation diagnostic containing the requested revision and the supported modern revisions; it does not silently enter the legacy path. |

This matrix describes Miftah's tested serving boundary, not a promise that every optional feature added to any future MCP revision is implemented. The SDK v2 serving entry owns protocol-era negotiation; Miftah continues to own broker routing, policy, audit, OAuth, profile state, upstream lifecycle, and cancellation propagation.

Confirmation-required tools, resource reads, prompt reads, and profile transitions return the MCP `input_required` result on the modern era. Miftah binds the continuation to the exact operation with bounded, integrity-protected, one-time state shared by the server factory, so a fresh request-scoped HTTP instance can safely finish the approval without retaining raw operation arguments. The SDK's legacy shim translates the same handler flow into form elicitation for initialized clients.

## Authenticated request context

The additive authenticated request-context API is the trust seam for future modern stateless handling. An embedding host supplies a verifier callback that returns `VerifiedHttpRequestClaims` only after it has authenticated the request. Miftah does not parse MCP `clientInfo`, arbitrary headers, request metadata, tool arguments, or a model-generated conversation ID into this boundary.
Expand All @@ -41,7 +60,7 @@ The additive authenticated request-context API is the trust seam for future mode

Claims are rejected at exact expiry. Provider failures and missing claims return only `AUTH_CONTEXT_UNAVAILABLE`; malformed claims return `AUTH_CONTEXT_INVALID`. Call `requireAuthenticatedRequestContext` in a modern account-sensitive path so an absent boundary cannot silently fall back to client metadata, a mutable default, or durable active-profile state.

The current CLI-owned Streamable HTTP server remains the documented legacy session-aware path and does not synthesize these claims from its static bearer token. Until a supported host supplies a verified per-chat claim and the modern protocol path is enabled, deploy a profile-scoped or operator-locked endpoint and do not claim chat-scoped switching.
The CLI-owned Streamable HTTP server accepts both the modern request-scoped protocol path and the legacy session-aware path, but it does not synthesize verified per-chat claims from its static bearer token. Its modern requests therefore begin from configured/default profile state and do not claim authenticated chat-scoped switching. A host that needs that capability must verify its own per-chat identity claims and supply the resulting boundary through `createMiftahServerFactory(configPath, { modernProfileContext })`; otherwise deploy a profile-scoped or operator-locked endpoint.

## Stateless profile-context handles

Expand All @@ -55,7 +74,7 @@ In modern mode, account-sensitive tool schemas include the reserved model-visibl

A valid handle selects a profile; it is not operation authorization or idempotency. Policy, approval, identity, lease, OAuth, and upstream checks still run for every request. Missing, malformed, tampered, expired, revoked, cross-principal, cross-chat, cross-deployment, and removed-profile handles return fixed `ProfileContextHandleErrorCode` failures. The modern runtime never reads or mutates `ProfileManager`'s legacy active profile.

The package exports `ProfileContextHandleServiceOptions`, `ModernProfileContextRuntimeOptions`, `MintedProfileContext`, `ResolvedProfileContext`, `ProfileContextReplacementAudit`, `ProfileContextKeyringProvider`, `ProfileContextKeyringSnapshot`, `ProfileContextKeyEpoch`, and `ProfileContextRevocationStore` for host integration. The current CLI-owned Streamable HTTP entry point does not enable this option; protocol-era negotiation and transport selection remain separate work, so existing stdio and session-aware HTTP behavior stays unchanged.
The package exports `ProfileContextHandleServiceOptions`, `ModernProfileContextRuntimeOptions`, `MintedProfileContext`, `ResolvedProfileContext`, `ProfileContextReplacementAudit`, `ProfileContextKeyringProvider`, `ProfileContextKeyringSnapshot`, `ProfileContextKeyEpoch`, and `ProfileContextRevocationStore` for host integration. The CLI-owned Streamable HTTP entry point negotiates modern and legacy eras but does not enable trusted `modernProfileContext` claims. An embedding host can pass that option to `createMiftahServerFactory`; existing legacy session-aware behavior remains available on the same endpoint.

## Type exports

Expand Down Expand Up @@ -83,7 +102,7 @@ The package root also exports `AuthenticatedRequestContext`, `AuthenticatedReque

For identity configurations, format-dependent structural constraints, unique `requiredForRisk` tuples, and `selectionMode: "explicit" | "confirmed"` are static. A selection mode requires `requiredForRisk`. For text probes, `validateConfig` runtime-validates equality between `expected.provider` and a static `probe.provider`; JSON probes do not permit a static provider.

Programmatic diagnostics expose `ConfigDiagnostic`, `MiftahErrorCode`, and `MiftahErrorDetails`. `MiftahErrorCode` includes the stable resource-template and resource-subscription protocol error categories. The wrapper factory exposes `MiftahRuntime`.
Programmatic diagnostics expose `ConfigDiagnostic`, `MiftahErrorCode`, and `MiftahErrorDetails`. `MiftahErrorCode` includes the stable resource-template and resource-subscription protocol error categories. The wrapper factories expose `MiftahRuntime` and `createMiftahServerFactory`.

## Compatibility policy

Expand Down
Loading