# MCP Server Schema — Layer 3 Entity Type # KNO Schema Version: 0.5.0 # # An MCP Server describes a Model Context Protocol server endpoint exposed # by the platform: its mount path, scopes, and discovery metadata. # # EXTENDS: document-schema.kno (which composes identity, history, quality) # CONFORMS TO: MCP Registry spec v0.1 (2025-12-11) # https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json # # DESIGN DECISIONS: # - DD-MCP-01: MCP servers are .kno entities; the integration manifest is derived (#1543) # - DD-MCP-02: Endpoint URL is composed at projection time from `endpoint_path` # and `${PSPACE_API_URL}` so a single .kno file is environment-portable. # - DD-MCP-03: Parallels agent-card-schema.kno (DD-A2A-01) — every protocol # surface has a schema and a derived discovery view. # - DD-MCP-04: `name` follows MCP Registry reverse-DNS identity (`space.possibility/*`) # so the same .kno file powers both the internal manifest and the public # /v0.1/servers registry projection (#1643, Epic: Copilot Cloud Agent support). # `name` is OPTIONAL; when absent, the registry projector derives it from # `slug` using the rule `pspace-{X}-mcp` → `space.possibility/{X}-mcp`. # - DD-MCP-05: `remotes[]` uses spec-standard `{baseUrl}` template variable so # environment portability is preserved through the registry projection — # clients substitute `baseUrl` at install time (#1644). `remotes[]` is # OPTIONAL; when absent, the registry projector synthesizes a single # `streamable-http` entry from `endpoint_path` and `${PSPACE_API_URL}`. # This keeps the authoring surface minimal (zero-maintenance generative # pattern): existing v0.1.0 files remain valid with no edits. # - DD-MCP-06: pspace-specific extensions live under `_meta."space.possibility/*"` # (reverse-DNS namespace we own, spec-sanctioned passthrough). Registry-populated # metadata lives under `_meta."io.modelcontextprotocol.registry/official"`. # # USE CASES: # - Platform MCP servers (identity, secrets, catalog, public, creator, admin, guides) # - Per-possibility MCP servers (future tenant-scoped tool surfaces) # # MAPS TO: McpServer interface in services/pspace-api/src/portico/types.ts # ============================================================================= # SCHEMA DECLARATION # ============================================================================= $schema: kno@0.0.9 # ============================================================================= # IDENTITY # ============================================================================= id: 01KMQRYG4M0XS5HZ2KQAPF3MCP slug: mcp-server-schema type: spec version: 0.5.0 # ============================================================================= # VISIBILITY DECLARATION (REQ-18) — collection default # ============================================================================= # MCP-server entities (content/mcp-servers/*.kno) are public reference knowledge # by default. Per REQ-18, individual entities MAY override with their own # `visibility:` field (last-write-wins at the entity level). # # Valid entity-level values (v0.5.0, #2256): # - public — anonymous discovery + invocation. INVARIANT: auth:none. # - authenticated — anonymous discovery hidden, but doc surfaces (/docs/mcp) # show the entry to logged-in users for developer reference. # INVARIANT: auth:bearer. # - internal — never on any public or authenticated surface; surfaced # only inside auth-gated admin areas (/dashboard/admin/*). # INVARIANT: auth:bearer (admin tools always require auth). # - restricted — reserved for partner-scoped surfaces; treated as `internal` # by the public docs renderer. # # Drives the four-surface contract per kno-system_architecture.md # § Agent Surface Integration and public-surface-parity.instructions.md. visibility: public # ============================================================================= # STANDARD TIER # ============================================================================= title: "MCP Server Schema" purpose: | Define the schema for MCP Server entities — machine-readable descriptions of Model Context Protocol server endpoints exposed by Possibility. **What is an MCP Server entity?** A .kno file declaring a single MCP mount: its name, mount path under the platform API base URL, human-readable description, and the OAuth scopes required for tool invocation. **Why a separate schema (not service-config)?** Per kno-foundational-principles § 0.6 (Schema Minimization), this passes the three-gate test: - Gate 1 (Distinctness): MCP server registrations are distinct from service-config entities (no `provider`, no `possibility_xri`, no lifecycle status). They are platform-scoped protocol mounts. - Gate 2 (Reusability): 7+ instances at introduction; growable as new domain-specific MCP surfaces are added. - Gate 3 (Clarity): Separating MCP server registry from service binding semantics keeps each schema focused. **Derived views:** 1. Internal manifest at /.well-known/integration projects all `content/mcp-servers/*.kno` files into `protocols.mcp.servers[]` via `scanBundles()` in services/pspace-api/src/portico/manifest.ts. 2. Public MCP Registry projection at /v0.1/servers (spec v0.1, 2025-12-11) projects the same .kno corpus into ServerDetail records so external tools (GitHub Copilot Cloud Agents, Claude Desktop, etc.) can discover and install pspace MCP servers without per-server maintenance. # ============================================================================= # RICH TIER — Taxonomy # ============================================================================= provenance: origin: id: 01KMQRYG4M0XS5HZ2KQAPF3MCP timestamp: "2026-04-20T00:00:00Z" tool: manual taxonomy: topics: - mcp - model-context-protocol - protocol-discovery - integration-manifest keywords: - mcp - mcp-server - tool-discovery - oauth-scope - manifest # ============================================================================= # RICH TIER — Relationships # ============================================================================= relationships: extends: - xri: "kno://specs/document-schema" reason: "MCP server entities inherit identity, history, and quality fields" related_to: - xri: "kno://specs/agent-card-schema" reason: "Sister schema for the A2A protocol surface; both describe protocol mounts" - xri: "kno://specs/api-spec" reason: "MCP servers expose tools that may correspond to REST endpoints documented as api-spec instances" # ============================================================================= # REQUIRED FIELDS # ============================================================================= fields: # --------------------------------------------------------------------------- # IDENTITY (inherited from document-schema, restated for clarity) # --------------------------------------------------------------------------- id: type: string format: ulid required: true description: "ULID of this MCP server entity (immutable birth identity)" slug: type: string required: true pattern: "^pspace-[a-z0-9-]+-mcp$" description: | Human-readable identifier. MUST follow the `pspace-{domain}-mcp` pattern to keep the manifest output consistent. Examples: `pspace-identity-mcp`, `pspace-guides-mcp`. type: type: string enum: - service-config required: true description: | Top-level kind. Reuses `service-config` (validated by the kno-spec type registry) with the `subtype` discriminator. Mirrors the agent-card-schema convention. subtype: type: string enum: - mcp-server required: true description: | Discriminator that identifies this entity as an MCP server registration among other service-config subtypes (e.g., `agent-card`). version: type: string format: semver required: true # --------------------------------------------------------------------------- # MCP-SPECIFIC FIELDS # --------------------------------------------------------------------------- name: type: string required: false pattern: "^[a-zA-Z0-9.-]+/[a-zA-Z0-9._-]+$" minLength: 3 maxLength: 200 description: | MCP Registry reverse-DNS identity (spec v0.1). The namespace segment before the `/` MUST be owned by the publisher; Possibility-hosted servers use `space.possibility/`. Convention: `space.possibility/{domain}-mcp` (e.g., `space.possibility/identity-mcp`). OPTIONAL. When absent, the registry projector derives `name` from `slug` using the deterministic rule `pspace-{X}-mcp` → `space.possibility/{X}-mcp`. Authors only need to set `name` when overriding the default namespace (e.g., per-possibility servers using a tenant-owned reverse-DNS). NOTE: This is distinct from `slug` (which remains the internal pspace identifier `pspace-{domain}-mcp` used for file naming, manifest keys, and human authoring). The projection layer maps `slug` → manifest and `name` (derived or explicit) → registry. title: type: string required: false minLength: 1 maxLength: 100 description: | Optional human-friendly display name shown in registry UIs and installer flows. Falls back to `name` when unset. endpoint_path: type: string required: true pattern: "^/mcp/[a-z0-9-]+$" description: | The mount path under the platform API base URL. The integration manifest composes the full endpoint as `${PSPACE_API_URL}${endpoint_path}` so one .kno file is environment-portable across staging, production, and developer overrides. description: type: string required: true minLength: 1 maxLength: 100 description: | One-sentence human-readable description of the server's purpose. The 100-char cap is a hard MCP Registry v0.1 constraint — descriptions longer than this will cause registry submission to fail. required_scopes: type: array items: type: string pattern: "^pspace:[a-z0-9-]+:[a-z0-9-]+$" required: true description: | OAuth scopes required to invoke tools on this server. Empty array is permitted only for unauthenticated discovery surfaces (e.g., public). Projected into `_meta."space.possibility/scopes".required[]` in the registry response (pspace extension, not a spec field). visibility: type: string enum: - public - authenticated - internal - restricted required: false description: | Entity-level visibility override (REQ-18). When omitted, inherits the collection default (`public`) declared at the top of this schema. - `public` — anonymous discovery and invocation. Listed on /docs/mcp for anonymous viewers, in the public MCP Registry projection (/v0.1/servers), and in /llms.txt. INVARIANT: auth:none. - `authenticated` — hidden from the anonymous MCP Registry projection and from /llms.txt, but listed on /docs/mcp for developer reference (the route still requires a bearer token to invoke). INVARIANT: auth:bearer. - `internal` — never on /docs/mcp or any public/authenticated projection. Surfaced only inside auth-gated admin areas (/dashboard/admin/docs). The detail route /docs/mcp/{slug} returns 404 for these slugs to avoid honeypot links. - `restricted` — reserved for partner-scoped surfaces (future); treated as `internal` by the public docs renderer today. Added in v0.5.0 (#2256). The `authenticated` value is new; v0.4.0 entities that omitted `visibility:` continue to inherit `public` and MUST be migrated explicitly per the lint (Rule 4). auth: type: string enum: - none - bearer required: false description: | Auth contract enforced at the route handler. Mirrors the `auth` field on the route registration in services/pspace-api/src/mcp/routes.ts. - `none`: The route handler accepts anonymous requests; the persona filter on the underlying server constrains the tool list to operations declaring `auth: none` in their .kno definitions. A bearer token MAY still be supplied for tier-aware behaviour but is not required. - `bearer` (default when omitted, for backward compatibility): the handler rejects requests without a valid bearer token (HTTP 401 with auth_help envelope). INVARIANTS (v0.5.0, #2256): - `visibility: public` ⇒ `auth: none` (honeypot shape #2055) - `visibility: authenticated` ⇒ `auth: bearer` (anonymous discovery is intentionally suppressed; bearer required to invoke) - `visibility: internal` ⇒ `auth: bearer` (admin tooling) - `visibility: restricted` ⇒ `auth: bearer` Advertising visibility:public while the handler requires a bearer token is the honeypot shape #2055 fixed for /mcp/public. `scripts/lint-api-contract-honesty.ts` enforces these invariants. Added in v0.3.0 (#2055, M52 P3.B.3). Existing v0.2.0 entries that omit `auth:` are treated as `bearer` by the registry projection and by the lint, preserving backward compatibility. # --------------------------------------------------------------------------- # MCP REGISTRY v0.1 FIELDS (optional except `remotes`, which is required # for the registry projection to function) # --------------------------------------------------------------------------- remotes: type: array required: false minItems: 1 description: | Remote transport declarations for MCP Registry consumers. Each entry describes how to connect to this MCP server. OPTIONAL. When absent, the registry projector synthesizes a single `streamable-http` remote from `endpoint_path` and `${PSPACE_API_URL}`: remotes: - type: streamable-http url: "{baseUrl}{endpoint_path}" variables: baseUrl: default: "${PSPACE_API_URL}" Authors only need to set `remotes[]` explicitly when overriding the default (e.g., declaring `sse` as an alternate transport, adding static auth headers, or hosting elsewhere). Explicit entries SHOULD still use the `{baseUrl}` template pattern to preserve environment portability. items: type: object properties: type: type: string enum: - streamable-http - sse required: true description: "MCP transport protocol. `streamable-http` is the modern default; `sse` is legacy." url: type: string required: true description: | Connection URL. SHOULD reference `{baseUrl}` template variable; the registry projector resolves this to `${PSPACE_API_URL}` for pspace-hosted servers. headers: type: object required: false description: "Optional static headers to include on every request (e.g., API keys for public endpoints)." variables: type: object required: false description: | Template variables referenced in `url` or `headers`. For pspace-hosted servers, `baseUrl.default` is set by the projector from `PSPACE_API_URL`; authors SHOULD NOT hardcode it in .kno. repository: type: object required: false description: | Optional source repository reference. For pspace-hosted servers this is typically omitted (the registry projector can derive a default from the monorepo) but may be set explicitly to point at the owning subfolder. properties: url: type: string format: uri required: true source: type: string enum: - github - gitlab - bitbucket - other required: true subfolder: type: string required: false icons: type: array required: false description: | Optional array of icon descriptors for registry UIs. Each entry follows MCP Registry v0.1 shape: `{src, mimeType, sizes, theme}`. items: type: object properties: src: type: string required: true description: "Icon URL (absolute or protocol-relative)." mimeType: type: string required: false sizes: type: string required: false description: "W×H pairs, e.g., `24x24 48x48`." theme: type: string enum: - light - dark required: false websiteUrl: type: string format: uri required: false description: "Optional marketing/landing URL for the MCP server." _meta: type: object required: false description: | Passthrough for spec-sanctioned extension metadata. Reverse-DNS keys only. Possibility extensions live under `space.possibility/*`; the registry server populates `io.modelcontextprotocol.registry/official` (status, publishedAt, updatedAt, isLatest) automatically — authors SHOULD NOT set that key directly. # ============================================================================= # QUALITY # ============================================================================= quality: completeness: 1.0 last_reviewed: "2026-04-20" review_status: stable # ============================================================================= # HISTORY # ============================================================================= _history: version: 3 created: "2026-04-20T00:00:00Z" created_by: "pspace-core-team" changes: - "v0.1.0: Initial schema introduced for #1543 (Phase 9.1, manifest generative-from-.kno)" - "v0.2.0 (2026-04-21): MCP Registry v0.1 conformance for #1644 (Epic #1643, Copilot Cloud Agent support). Added optional reverse-DNS `name` (derived from `slug` when absent), optional `title`, optional `remotes[]` (synthesized from `endpoint_path`+`${PSPACE_API_URL}` when absent), optional `repository`, `icons[]`, `websiteUrl`, `_meta` passthrough. Tightened `description` to 1–100 chars. MINOR (additive) per RFC-007 — all existing v0.1.0 authorings remain valid with only a `$schema` pointer bump; the registry projection is fully generative from the existing field set, preserving the zero-maintenance contract from DD-MCP-02." - "v0.3.0 (2026-04-27, #2055, M52 P3.B.3): Added optional `auth: none | bearer` field to mirror the route-handler auth contract in services/pspace-api/src/mcp/routes.ts. Required so the lint at scripts/lint-api-contract-honesty.ts can enforce the visibility:public ⇒ auth:none invariant that closed the /mcp/public honeypot. MINOR (additive); v0.2.0 entries omitting `auth:` are treated as `bearer` by the projection." - "v0.4.0 (2026-04-28, M52 P4.1, #2139): Declared collection-default `visibility: public` at the schema top level so REQ-18 four-surface enforcement applies to mcp-server entities. MINOR (additive)." - "v0.5.0 (2026-04-29, #2256): Added entity-level `visibility` field with enum `[public, authenticated, internal, restricted]`. Added the `authenticated` tier so authenticated-only servers can be hidden from anonymous discovery but kept on /docs/mcp as developer reference. Tightened the auth invariant: visibility:public ⇒ auth:none, and visibility:{authenticated,internal,restricted} ⇒ auth:bearer. Closes the admin-MCP-leak shape (admin servers were inheriting visibility:public from the collection default and surfacing in the public sidebar). MINOR (additive); v0.4.0 entities that omitted entity-level `visibility:` MUST now declare it explicitly per the lint (Rule 4)."