Files
Patrick Buckley 471d1a3311 docs: audit documentation for 1.4 / 1.5 state
Systematic pass over every doc under docs/, the root-level README /
QUICKSTART / CONTRIBUTING, and the PlantUML diagrams.  Memory and docs
had drifted against the code since 1.2 — this catches them up to the
1.4.0 release and the 1.5.0a1 experimental line.

User-facing fixes
- README: fix broken docs/mcp.md link (→ mcp-registry.md); channel
  gateway entry reflects shipped Discord + Slack adapters instead of
  "Slack/Teams planned"; diagrams table mentions both.
- QUICKSTART: docs/*.md relative links were wrong from the repo root;
  wizard version bumped from 0.5.4.
- CONTRIBUTING: add dev extra plus the ruff / mypy / pytest commands
  we actually expect before push.

Reference docs
- architecture.md: 19 tool schemas (was 15), 18 admin tabs (was 14),
  turnstone-bootstrap added to entry-points table, OpenAI provider
  file split (chat/responses/common) documented, 38 SDK event
  dataclasses (was 27 and referenced deleted mq/protocol.py), Slack
  adapter + multi-adapter gateway, plan_agent/task_agent naming,
  governance admin-panel rewrite.
- api-reference.md: full attachment endpoints (POST/GET/content/
  DELETE on /v1/api/workstreams/{ws_id}/attachments) plus the
  multipart mode on POST /v1/api/workstreams/new.
- channels.md: Slack Setup section (Socket Mode app creation, OAuth
  scopes, tokens), Slack CLI/env reference in config table, combined-
  adapter architecture diagram.
- console.md: 18-tab listing (was 13) with Channels/Models/Nodes/TLS
  descriptions and ConfigStore live-edit note.
- docker.md: Slack env vars block; image entry-point list now
  includes turnstone / turnstone-bootstrap.
- sdk.md: attachments methods on the server client, attachments
  example (upload-then-send and at-creation), event count fixed.
- releasing.md: four-track table (stable/1.0, 1.3, 1.4 + main 1.5);
  promotion workflow uses 1.5 / 1.6 numbering.
- settings.md: plan_model / task_model / plan_effort / task_effort
  overrides section.
- governance.md: skill naming (/skill, `skill` field — not /template),
  Prompts/Judge tabs called out.
- security.md: two-token-types wording; src claim values match the
  AuthResult source strings actually emitted.
- mcp-registry.md: SDK package name is @turnstone/sdk.
- tools.md: plan / task renamed to plan_agent / task_agent in the
  section headings and summary table; primary-key table matched.
- design/consistent-hash-ring.md: dead direct-http-transport.md
  pointer redirected to architecture.md.

Diagrams
- 02-package-structure: drop phantom chat.py entry point, add admin
  and bootstrap, add slack/bot.py, rename channels/gateway.py →
  channels/cli.py.
- 16-channel-architecture: Slack is no longer "(future)", add a
  SlackBot class and the slack-bolt Socket Mode edges; wire the new
  bot into ChannelService.  PNGs regenerated from both puml sources.
2026-04-16 16:01:24 -07:00

7.0 KiB

MCP Registry Integration

Turnstone integrates with the official MCP Registry to let administrators discover and install MCP servers directly from the console admin panel.

Overview

The MCP Registry is maintained by the Agentic AI Foundation (Linux Foundation) and serves as the canonical discovery layer for MCP servers. Turnstone queries its REST API (v0.1) for server metadata and provides a one-click install flow.

Three sources of MCP servers coexist in Turnstone:

Source Badge Description
Config CONFIG (magenta) Imported from config.toml or JSON file. Read-only in admin UI.
Manual MANUAL (cyan) Added through the admin UI or API. Full CRUD.
Registry REGISTRY (green) Installed from the MCP Registry. Tracked by registry_name.

Admin UI

The MCP admin tab has two views, toggled by a pill selector:

Servers View

Lists all installed MCP servers regardless of source. Each server shows:

  • Source badge — CONFIG, MANUAL, or REGISTRY
  • Transport badge — stdio or streamable-http
  • Tool/resource/prompt counts — aggregated across cluster nodes
  • Per-node connection status — connected (magenta dot), error (red), disabled (gray)
  • Actions — Edit / Delete (DB-managed servers only)

Clicking a server name opens the detail modal. For registry-installed servers, the detail modal includes a Registry section showing the registry name, installed version, description, and website link.

Registry View

Search and browse the MCP Registry. Switching to this view auto-loads a listing. Type a query and press Enter or click Search to filter.

Each result card shows:

  • Server name and description
  • Source type badges — remote (streamable-http), npm, pypi
  • Version number
  • Install / Installed / Update button

Install flow

  • One-click: Remote servers with no required headers or URL variables install immediately — no modal, no form. The server is added to the database, all cluster nodes are notified, and a toast confirms success.

  • Modal: Servers that require configuration (API keys, headers, URL template variables) or offer multiple install sources (both remote and package) open an install modal with:

    • Source selector (radio group) — only shown when both remote and package are available
    • Dynamic form fields for required/optional configuration
    • Secret fields rendered as password inputs

Configuration

Registry URL

By default, Turnstone queries https://registry.modelcontextprotocol.io. Override this for enterprise or private registries:

Via admin Settings tab:

Set mcp.registry_url to your registry's base URL.

Via config.toml:

[mcp]
registry_url = "https://registry.internal.example.com"

The resolution order is: database setting > config.toml > default.

API Endpoints

Both endpoints require admin.mcp permission.

GET /v1/api/admin/mcp-registry/search?search=github&limit=20&cursor=...

Query parameters:

Parameter Type Default Description
search string "" Search query. Empty returns a browsable listing.
limit integer 20 Results per page (max 100).
cursor string Opaque cursor from next_cursor for pagination.

The response annotates each server with installed, installed_server_id, installed_version, and update_available by cross-referencing the mcp_servers table.

Install

POST /v1/api/admin/mcp-registry/install
{
  "registry_name": "io.example/mcp-server",
  "source": "remote",
  "index": 0,
  "name": "",
  "variables": {},
  "env": {"API_KEY": "sk-..."},
  "headers": {"Authorization": "Bearer ..."}
}
Field Required Description
registry_name Yes Server name from registry search results.
source Yes "remote" (streamable-http) or "package" (npm/pypi).
index No Which remote or package entry to use (default 0).
name No Custom server name. Auto-derived from registry name if empty.
variables No Values for URL template {var} placeholders.
env No Environment variable values for package servers.
headers No Header values for remote servers.

On success, the server is created in the database and all cluster nodes are automatically reloaded. Returns the created McpServerDetail.

Errors: 400 (validation), 404 (not found in registry), 409 (already installed or name collision), 502 (registry unreachable).

SDK

Python

from turnstone.sdk.console import TurnstoneConsole

with TurnstoneConsole("http://localhost:8081", token="...") as client:
    # Search
    results = client.search_mcp_registry(q="github", limit=10)
    for srv in results.servers:
        print(f"{srv.name} v{srv.version} - {srv.description}")

    # Install a remote server
    detail = client.install_from_registry(
        "io.example/mcp-server",
        "remote",
        headers={"Authorization": "Bearer sk-..."},
    )
    print(f"Installed: {detail.name}")

TypeScript

import { TurnstoneConsole } from "@turnstone/sdk";

const client = new TurnstoneConsole({
  baseUrl: "http://localhost:8081",
  token: "...",
});

// Search
const results = await client.searchMcpRegistry({ q: "github", limit: 10 });
for (const srv of results.servers) {
  console.log(`${srv.name} v${srv.version} - ${srv.description}`);
}

// Install
const detail = await client.installFromRegistry({
  registry_name: "io.example/mcp-server",
  source: "remote",
  headers: { Authorization: "Bearer sk-..." },
});

Storage

Registry-installed servers are stored in the existing mcp_servers table with three additional columns (migration 019):

Column Type Description
registry_name TEXT (nullable, unique) Reverse-DNS name from the registry (e.g. io.example/mcp-server).
registry_version TEXT Version at time of install.
registry_meta TEXT (JSON) Snapshot of description, title, website, icons for display.

The partial unique index on registry_name prevents duplicate installs while allowing multiple non-registry servers with NULL registry_name.

Package Type Support

Registry Type Transport Command Status
Remote (streamable-http) streamable-http — (URL-based) Supported
npm stdio npx -y @scope/package@version Supported
pypi stdio uvx package==version Supported
oci Not supported (no runtime available)
nuget Not supported
mcpb Not supported

For npm and pypi packages, the corresponding runtime (node/npx or python/uvx) must be available on the cluster nodes. Connection failures due to missing runtimes appear in the per-node MCP status display.