mirror of
https://github.com/turnstonelabs/turnstone.git
synced 2026-08-12 23:12:23 -06:00
471d1a3311
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.
194 lines
7.0 KiB
Markdown
194 lines
7.0 KiB
Markdown
# MCP Registry Integration
|
|
|
|
Turnstone integrates with the [official MCP Registry](https://registry.modelcontextprotocol.io) 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](https://www.linuxfoundation.org/press/linux-foundation-announces-the-formation-of-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:**
|
|
|
|
```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.
|
|
|
|
### Search
|
|
|
|
```
|
|
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
|
|
```
|
|
|
|
```json
|
|
{
|
|
"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
|
|
|
|
```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
|
|
|
|
```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.
|