XProtocol MCP Adapter — Full Specification
Protocol Version: 0.1 (Draft)
Date: 2026-05-31
License: CC BY 4.0 (this document) · Apache 2.0 (code)
Status: Proposed — reference implementation forthcoming
Namespace: xp.mcp.*
Depends on: XProtocol-Specification.md (core protocol)
Repos:
- gitlab.com/xprotocol/xprotocol-mcp-adapter — production adapter
- gitlab.com/xprotocol/xprotocol-devserver — local dev + demo bundle
Abstract
The XProtocol MCP Adapter is a universal bridge between the MCP (Model Context Protocol) ecosystem and the XProtocol ecosystem. It operates bidirectionally:
Direction 1 — MCP → XProtocol: Any existing MCP server becomes an XProtocol endpoint automatically. Point the adapter at an MCP server, and it presents that server's tools as a signed, schema-native XProtocol endpoint — with no changes to the MCP server, no SDK integration, and no schema writing required.
Direction 2 — XProtocol → MCP: Any XProtocol endpoint becomes an MCP tool set automatically. Any MCP-capable AI agent (Claude, Claude Code, Claude Desktop, or any conformant MCP client) can interact with any XProtocol-native service — without bespoke integration code, without per-service SDKs, and without knowing anything about XProtocol's internals.
The adapter is the zero-friction adoption path for organizations that have already invested in MCP. Their existing MCP servers join the XProtocol ecosystem in minutes. Their existing MCP clients gain access to every XProtocol-native service simultaneously.
1. Design Principles
1.1 — Zero Changes to Existing Systems
The adapter never requires modifications to existing MCP servers or existing MCP clients. It is purely a translation layer. An MCP server that has never heard of XProtocol becomes a full XProtocol endpoint. An MCP client that has never heard of XProtocol gains access to all XProtocol services.
1.2 — Configuration, Not Code
Connecting an MCP server to XProtocol requires a YAML configuration file — no code, no SDK integration, no schema authoring. The adapter derives everything it needs from the MCP server's own tool definitions.
1.3 — Schema Translation is Deterministic
The translation between MCP tool definitions and XProtocol schema contracts follows a defined, deterministic algorithm. Given the same MCP tool definition, every adapter instance produces the same XProtocol schema. This guarantees interoperability between adapter instances and predictable behavior for AI agents consuming the generated schemas.
1.4 — Identity is the Adapter's Responsibility
MCP servers have no cryptographic identity. XProtocol requires one. The adapter provides identity — it holds Ed25519 and X25519 keypairs and presents them as the endpoint identity of each wrapped MCP server. For organizations, this adapter key is registered in the organizational key hierarchy, giving the wrapped services inherited organizational trust.
1.5 — Bidirectional by Default
The adapter is not a one-way bridge. It simultaneously exposes MCP servers as XProtocol endpoints AND exposes XProtocol endpoints as MCP tools. A single adapter instance can bridge in both directions at once, making it a universal protocol gateway rather than a one-way migration tool.
2. Architecture
2.1 — Bidirectional Bridge
┌──────────────────────────────────────────────────────────────────┐
│ XProtocol MCP Adapter │
│ │
│ ┌─────────────────┐ ┌─────────────────────────┐ │
│ │ MCP Listener │ │ XProtocol Client │ │
│ │ (stdio / SSE) │ │ (signs + encrypts) │ │
│ └────────┬────────┘ └──────────┬──────────────┘ │
│ │ │ │
│ ┌────────▼──────────────────────────────────▼──────────────┐ │
│ │ Translation Engine │ │
│ │ │ │
│ │ MCP tool def → XProtocol schema contract │ │
│ │ XProtocol schema → MCP tool definition │ │
│ │ MCP tool call → XProtocol signed event │ │
│ │ XProtocol response → MCP tool result │ │
│ │ XProtocol schema → GBNF grammar (auto-compiled) │ │
│ └────────┬──────────────────────────────────┬──────────────┘ │
│ │ │ │
│ ┌────────▼────────┐ ┌──────────▼──────────────┐ │
│ │ XProtocol │ │ MCP Client │ │
│ │ Endpoint │ │ (tool caller) │ │
│ │ (receives │ │ (calls wrapped │ │
│ │ events) │ │ XP endpoints) │ │
│ └─────────────────┘ └─────────────────────────┘ │
│ │
│ Identity: Ed25519 + X25519 keypair (one per adapter instance) │
└──────────────────────────────────────────────────────────────────┘
│ │
▼ ▼
Existing MCP servers XProtocol relay
(unchanged) + XProtocol endpoints
2.2 — Component Responsibilities
MCP Listener: Accepts connections from MCP clients via stdio
(for local agents like Claude Code) or SSE (for remote MCP clients).
Implements the MCP JSON-RPC protocol — tools/list, tools/call,
resources/list, resources/read, prompts/list, prompts/get.
XProtocol Client: Holds the adapter's Ed25519 and X25519 keypairs. Signs all outgoing XProtocol events. Encrypts payloads to recipient keys. Connects to the XProtocol relay for event routing. Handles XProtocol endpoint discovery.
Translation Engine: The core of the adapter. Converts between MCP and XProtocol representations in both directions. Deterministic, stateless, testable independently. Described fully in §4.
XProtocol Endpoint: Receives incoming XProtocol events addressed to the adapter's key — these are calls to wrapped MCP servers coming from XProtocol clients. Translates them to MCP tool calls and returns XProtocol response events.
MCP Client: Makes outgoing MCP tool calls to connected MCP servers on behalf of XProtocol clients who are invoking wrapped MCP tools.
2.3 — Deployment Models
Self-hosted (enterprise): Organization runs the adapter internally, pointed at internal MCP servers. Adapter key registered in organizational key hierarchy. All XProtocol clients in the organization access internal MCP tools via XProtocol. All MCP clients (Claude Code, etc.) access XProtocol services via MCP.
[Internal MCP servers] ←→ [Adapter] ←→ [XProtocol relay] ←→ [XProtocol ecosystem]
↕
[Claude Code / MCP clients]
Sidecar (per-server): One adapter instance per MCP server. Each wrapped server gets its own XProtocol identity. Better isolation, clearer trust boundaries. Recommended for production deployments where individual service identity matters.
Managed service: Adapter hosted by a third party (Explan or community providers). Organizations configure via web UI — point at MCP servers, receive an XProtocol endpoint. No self-hosting required. Fastest path to adoption.
Dev bundle (XProtocol-DevServer): Local development only. Single binary combining adapter + local relay + minimal Event Store. Run one command, get the full XProtocol stack locally. Not for production. See §10.
3. Configuration
The adapter is configured entirely via a YAML file. No code is required to bridge existing MCP servers.
3.1 — Full Configuration Schema
# xprotocol-mcp-adapter.yml
# ─── Identity ────────────────────────────────────────────────────
identity:
# Path to Ed25519 + X25519 keypair file
# Generated on first run if not present: xprotocol-adapter keygen
key_file: ~/.xprotocol/adapter.key
# Human-readable name published in xp.endpoint.announce
display_name: "Acme Corp XProtocol Adapter"
# Optional: parent key for organizational trust chain
parent_key: ed25519:abc123...
parent_delegation_event: /path/to/delegation.json
# ─── XProtocol relay connection ──────────────────────────────────
relay:
urls:
- wss://relay.xprotocol.ai
- wss://relay2.xprotocol.ai # fallback
reconnect_interval_seconds: 5
event_ttl_seconds: 3600
# ─── MCP servers to expose as XProtocol endpoints ────────────────
mcp_sources:
- name: filesystem
# stdio transport (local process)
transport: stdio
command: npx @modelcontextprotocol/server-filesystem /data
args: []
env:
DATA_DIR: /var/data
# XProtocol namespace for generated schemas
# Tool "read_file" → kind "com.acme.filesystem.read_file"
xprotocol_namespace: com.acme.filesystem
# Capability inference: auto | explicit
# auto: infer capabilities from tool name patterns
# explicit: list capabilities manually below
capability_inference: auto
# Explicit capabilities (used when capability_inference: explicit)
capabilities:
- filesystem.read
- filesystem.write
# Schema generation overrides (optional)
# Use to enrich auto-generated semantic annotations
# or fix vague descriptions from source MCP servers
schema_overrides:
read_file:
description: "Read contents of a file from the data directory"
required_capability: filesystem.read
semantic:
use_when: "Agent needs to read the full text or binary content of a specific file"
do_not_use_when: "Agent wants to list files in a directory — use list_directory"
example_inputs:
- { path: "reports/q1.csv", encoding: "utf-8" }
handle_thing:
description: "Process an incoming data record through the validation pipeline"
semantic:
intent_verbs: ["validate", "process", "submit"]
data_subjects: ["record", "data"]
use_when: "Agent needs to validate and submit a data record for processing"
- name: salesforce-crm
# SSE transport (remote MCP server)
transport: sse
url: https://mcp.salesforce.com/sse
auth:
type: bearer
token_env: SALESFORCE_MCP_TOKEN # reads from environment variable
xprotocol_namespace: com.salesforce.crm
capability_inference: auto
rate_limit:
requests_per_minute: 100
- name: postgres
transport: stdio
command: npx @modelcontextprotocol/server-postgres
args: ["postgresql://localhost:5432/mydb"]
xprotocol_namespace: com.acme.database
capability_inference: auto
- name: internal-api
transport: sse
url: http://localhost:3001/mcp
xprotocol_namespace: com.acme.internal
# Expose only specific tools (allowlist)
tool_allowlist:
- get_customer
- create_order
- update_status
capability_inference: explicit
capabilities:
- internal.read
- internal.write
# ─── XProtocol endpoints to expose as MCP tools ──────────────────
xprotocol_sources:
- name: weather-service
# XProtocol endpoint discovery
endpoint: xp://weather.example.com
# OR: direct key + relay
# key: ed25519:abc123...
# relay: wss://relay.xprotocol.ai
# MCP tool name prefix to avoid collisions
mcp_tool_prefix: weather_
# Which schemas to expose as tools (empty = all)
schema_filter:
- weather.current.get
- weather.forecast.get
- name: xprotocol-chat
endpoint: xp://xprotocolchat.ai
mcp_tool_prefix: chat_
schema_filter: [] # expose all schemas
# ─── MCP server interface ─────────────────────────────────────────
mcp_server:
# How MCP clients connect to this adapter
transport: stdio # stdio | sse
sse_port: 8765 # only used when transport: sse
sse_host: 127.0.0.1
# ─── Discovery ───────────────────────────────────────────────────
discovery:
# Publish DNS TXT record for XProtocol endpoint discovery
publish_dns: false
# Serve /.well-known/xprotocol-endpoint on this port
well_known_port: 8766
well_known_host: 0.0.0.0
# ─── Logging ─────────────────────────────────────────────────────
logging:
level: info # debug | info | warn | error
format: json # json | text
output: stdout # stdout | /path/to/file
3.2 — Minimal Configuration
The simplest possible configuration — wrap one MCP server, expose as an XProtocol endpoint:
identity:
key_file: ~/.xprotocol/adapter.key
display_name: "My Adapter"
relay:
urls:
- wss://relay.xprotocol.ai
mcp_sources:
- name: my-server
transport: stdio
command: npx my-mcp-server
xprotocol_namespace: com.myorg.myserver
Three relay lines, four source lines. That's the complete configuration to bring any MCP server into the XProtocol ecosystem.
4. Schema Translation Engine
4.1 — MCP Tool → XProtocol Schema (Direction 1)
The translation algorithm is deterministic. Given the same MCP tool definition, the output XProtocol schema is always identical.
Input — MCP tool definition:
{
"name": "read_file",
"description": "Read the contents of a file at the specified path",
"inputSchema": {
"type": "object",
"properties": {
"path": {
"type": "string",
"description": "Relative path to the file"
},
"encoding": {
"type": "string",
"enum": ["utf-8", "base64"],
"description": "Output encoding",
"default": "utf-8"
}
},
"required": ["path"]
}
}
Output — XProtocol schema contract:
{
"kind": "com.acme.filesystem.read_file",
"version": "1.0.0",
"description": "Read the contents of a file at the specified path",
"semantic": {
"domain": "filesystem",
"intent_verbs": ["read", "get", "fetch", "retrieve", "load"],
"data_subjects": ["file", "document", "content"],
"use_when": "Agent needs to read the contents of a file at a known path",
"do_not_use_when": "Agent wants to list available files — use com.acme.filesystem.list_directory instead",
"related_schemas": ["com.acme.filesystem.write_file", "com.acne.filesystem.list_directory"],
"description_quality_score": 0.78
},
"source": {
"type": "mcp_adapter",
"mcp_server": "filesystem",
"mcp_tool": "read_file",
"adapter_version": "0.1.0"
},
"payload": {
"type": "object",
"properties": {
"path": {
"type": "string",
"description": "Relative path to the file"
},
"encoding": {
"type": "string",
"enum": ["utf-8", "base64"],
"description": "Output encoding",
"default": "utf-8"
}
},
"required": ["path"]
},
"response": {
"kind": "com.acme.filesystem.read_file.result",
"payload": {
"type": "object",
"properties": {
"content": { "type": "string" },
"encoding": { "type": "string" },
"mimeType": { "type": "string" }
}
}
},
"error_response": {
"kind": "xp.error",
"payload": { "$ref": "xp.error.schema" }
},
"auth": {
"required_capability": "com.acme.filesystem.read"
},
"gbnf_grammar": "<auto-compiled from payload schema>"
}
Translation rules:
| MCP field | XProtocol field | Rule |
|---|---|---|
name |
kind |
{namespace}.{tool_name} |
description |
description |
Direct copy |
inputSchema |
payload |
Direct copy (both JSON Schema) |
| (inferred) | response.kind |
{kind}.result |
| (derived) | auth.required_capability |
See §4.3 |
| (compiled) | gbnf_grammar |
Auto-compiled from payload schema |
| (generated) | source |
Provenance metadata |
| (derived) | semantic |
Auto-generated from tool name + description — see §4.6 |
4.2 — XProtocol Schema → MCP Tool (Direction 2)
Input — XProtocol schema contract:
{
"kind": "weather.current.get",
"description": "Get current weather conditions for a location",
"payload": {
"type": "object",
"properties": {
"location": { "type": "string", "description": "City name or coordinates" },
"units": { "type": "string", "enum": ["metric", "imperial"] }
},
"required": ["location"]
}
}
Output — MCP tool definition:
{
"name": "weather_current_get",
"description": "Get current weather conditions for a location\n\n[XProtocol: weather.current.get via xp://weather.example.com]",
"inputSchema": {
"type": "object",
"properties": {
"location": { "type": "string", "description": "City name or coordinates" },
"units": { "type": "string", "enum": ["metric", "imperial"] }
},
"required": ["location"]
}
}
Translation rules:
| XProtocol field | MCP field | Rule |
|---|---|---|
kind |
name |
Dots replaced with underscores; prefix prepended |
description |
description |
Copy + append XProtocol provenance note |
payload |
inputSchema |
Direct copy (both JSON Schema) |
4.3 — Capability Inference
MCP has no capability model. XProtocol requires one. The adapter
infers capabilities from tool name patterns when capability_inference: auto.
Inference rules (applied in order, first match wins):
| Tool name pattern | Inferred capability |
|---|---|
read_*, get_*, list_*, search_*, find_* |
{namespace}.read |
write_*, create_*, insert_*, add_* |
{namespace}.write |
update_*, edit_*, modify_*, patch_* |
{namespace}.write |
delete_*, remove_*, destroy_* |
{namespace}.delete |
execute_*, run_*, invoke_*, call_* |
{namespace}.execute |
admin_*, manage_*, configure_* |
{namespace}.admin |
| (no match) | {namespace}.access |
Organizations that need finer-grained control use
capability_inference: explicit and list capabilities manually.
4.4 — GBNF Grammar Compilation
Every MCP tool wrapped by the adapter automatically gets a GBNF
grammar compiled from its inputSchema. This makes every wrapped
MCP server immediately usable by constrained LLM generation —
a 7B local model can call any MCP server through the adapter
without ever producing an invalid invocation.
The compilation follows the same algorithm as the XProtocol core spec's schema-to-grammar pipeline:
JSON Schema (inputSchema)
│
▼
Type analysis (object, string, number, enum, array, required fields)
│
▼
GBNF production rules per field type
│
▼
Composition into complete grammar for the tool's input shape
│
▼
Stored in schema contract's `gbnf_grammar` field
Example — compiled grammar for read_file:
root ::= "{" ws path-field "," ws encoding-field? "}"
path-field ::= "\"path\"" ":" ws string
encoding-field ::= "\"encoding\"" ":" ws encoding-enum
encoding-enum ::= "\"utf-8\"" | "\"base64\""
string ::= "\"" [^"]* "\""
ws ::= [ \t\n]*
This grammar makes it structurally impossible for an LLM to generate
an invalid read_file call. The path field is always present
(required), encoding is always one of the two valid values.
4.5 — Resource and Prompt Translation
MCP exposes not just tools but also resources (data sources) and prompts (reusable prompt templates). The adapter translates these as well:
MCP resources → XProtocol subscriptions: MCP resources with URI templates become XProtocol subscription schemas — clients can subscribe to resource URIs as XProtocol event streams.
MCP prompts → XProtocol schema contracts:
MCP prompt definitions become XProtocol schemas with
kind: "{namespace}.prompt.{prompt_name}". Prompt arguments map
to the schema payload. Prompt text is returned as the response payload.
4.6 — Two-Phase Agent Interaction and Semantic Annotation
The adapter addresses both phases of agent interaction — not just the execution phase that MCP already handles.
The gap the adapter fills:
MCP specifies Phase 2 (execution) well: tool names, input schemas, and description strings give an agent what it needs to call a tool correctly once it has decided to. What MCP does not specify is Phase 1 (discovery): how does an agent decide which tool to call from a catalog of dozens or hundreds? The answer in both MCP and the naive adapter is: read the description string. If the description is vague, the tool is undiscoverable.
The adapter adds Phase 1 support through three mechanisms:
1. Auto-generated semantic annotations
During schema translation (§4.1), the adapter auto-generates a
semantic field for every wrapped MCP tool. The auto-generation
derives:
intent_verbs— from the tool name prefix (using the same rules as capability inference §4.3 but mapped to verb vocabulary):
| Name prefix | Generated intent_verbs |
|---|---|
read_, get_, fetch_ |
["read", "get", "fetch", "retrieve"] |
list_, search_, find_ |
["list", "search", "find", "query"] |
create_, write_, add_ |
["create", "write", "add", "insert"] |
update_, edit_, patch_ |
["update", "edit", "modify", "patch"] |
delete_, remove_ |
["delete", "remove", "destroy"] |
execute_, run_, invoke_ |
["execute", "run", "invoke", "call"] |
-
data_subjects— from the tool name suffix (the noun part after the verb prefix):read_file→["file"],list_opportunities→["opportunity", "opportunities"] -
domain— from the namespace:com.acme.filesystem→"filesystem",com.salesforce.crm→"crm" -
related_schemas— other schemas in the same namespace with complementary verb prefixes: ifread_fileis being processed,write_file,delete_file, andlist_directoryin the same namespace are automatically listed as related schemas -
description_quality_score— computed from the source description length, presence of action verbs, presence of noun subjects, and absence of vague phrases ("does something", "handles", "manages"):
| Description quality indicator | Score contribution |
|---|---|
| Length ≥ 50 characters | +0.20 |
| Contains action verb | +0.20 |
| Contains data subject noun | +0.20 |
| Contains "when to use" guidance | +0.20 |
| Free of vague filler phrases | +0.20 |
Auto-generated semantic annotations are marked with
"auto_generated": true in the semantic field. Schema authors
and adapter operators can override any field with explicit values
in the configuration's schema_overrides section.
2. Description quality enforcement
Conformant adapters MUST flag schemas with low description quality
in the xp.endpoint.announce event:
{
"kind": "xp.endpoint.announce",
"payload": {
"low_quality_schemas": [
{
"kind": "com.acme.filesystem.handle_thing",
"description_quality_score": 0.20,
"issue": "Description too vague for reliable agent discovery"
}
]
}
}
Conformant adapters SHOULD reject schema publication for tools
whose descriptions score below 0.20 (the minimum floor) and MUST
log a warning for tools scoring below 0.40. The threshold is
configurable per mcp_source:
mcp_sources:
- name: my-server
description_quality_threshold: 0.40 # warn below this
description_quality_floor: 0.20 # reject below this
3. xp.schema.describe support
The adapter implements xp.schema.describe (defined in
XProtocol-Specification.md §Schema Contracts) — the Phase 1
discovery event. When an XProtocol client sends
xp.schema.describe to the adapter, the adapter:
- Searches its local schema registry against the query's
intent,domain,data_subjects, andintent_verbs - Ranks matches by relevance against
semantic.intent_verbs,semantic.data_subjects, andsemantic.use_when - Returns a ranked list of matching schemas with relevance scores
and
use_whenexcerpts
This makes the adapter a self-describing semantic catalog — an
agent can send one xp.schema.describe event and get back ranked
tool recommendations for its current intent, without knowing
anything about what tools the wrapped MCP server offers.
The honest limitation:
Auto-generated semantic annotations are better than nothing but
are not a substitute for human-authored annotations. The auto-
generation derives intent verbs and data subjects from tool names —
which means it is only as good as the tool names themselves. A tool
named handle_thing produces useless auto-annotations. A tool named
get_opportunity_by_stage produces good ones.
The practical recommendation: when deploying the adapter against
MCP servers you control, invest in good tool names and descriptions
in the source MCP server. The adapter will carry them forward
faithfully and enrich them. When deploying against third-party MCP
servers you don't control, use schema_overrides in the adapter
configuration to add use_when, do_not_use_when, and example
inputs for the most important tools.
5.1 — Inbound XProtocol Event → MCP Tool Call
When an XProtocol client calls a wrapped MCP server:
1. Adapter receives xp.event addressed to its key
- Verifies Ed25519 signature
- Decrypts payload with adapter's X25519 key
2. Looks up the event kind in its schema registry
- Finds: "com.acme.filesystem.read_file" → MCP server "filesystem", tool "read_file"
3. Checks sender's capability against required capability
- Sender has capability "com.acme.filesystem.read"? ✓ proceed
- Does not have capability? → return xp.error AUTHORIZATION_INSUFFICIENT
4. Translates XProtocol payload to MCP tool call arguments
- XP payload: { "path": "docs/readme.md", "encoding": "utf-8" }
- MCP call: tools/call { name: "read_file", arguments: { path: "docs/readme.md", encoding: "utf-8" } }
5. Sends MCP tool call to upstream MCP server
6. Receives MCP tool result
7. Translates MCP result to XProtocol response event
- kind: "com.acme.filesystem.read_file.result"
- payload: { content: "...", encoding: "utf-8", mimeType: "text/markdown" }
- correlation_id: (from original request)
8. Signs and encrypts response event to original sender's key
9. Sends via relay
5.2 — MCP Client Tool Call → XProtocol Event
When an MCP client (Claude Code, etc.) calls an XProtocol-native service:
1. MCP client calls: tools/call { name: "weather_current_get", arguments: { location: "San Francisco" } }
2. Adapter looks up tool in XProtocol source registry
- "weather_current_get" → XProtocol endpoint xp://weather.example.com, kind "weather.current.get"
3. Translates MCP arguments to XProtocol event payload
- MCP args: { location: "San Francisco" }
- XP payload: { location: "San Francisco" } (direct mapping)
4. Constructs and signs XProtocol event
- kind: "weather.current.get"
- sender: <adapter key>
- recipient: <weather service key>
- payload: encrypted { location: "San Francisco" }
5. Sends via relay to XProtocol weather endpoint
6. Receives XProtocol response event
- Verifies signature
- Decrypts payload
7. Translates XProtocol response to MCP tool result
- MCP result: { content: [{ type: "text", text: "Current weather: 65°F, partly cloudy..." }] }
8. Returns MCP tool result to MCP client
5.3 — Error Translation
XProtocol errors map to MCP errors deterministically:
| XProtocol error code | MCP error | Message |
|---|---|---|
AUTHORIZATION_INSUFFICIENT |
InvalidRequest |
"Insufficient capability for this operation" |
SCHEMA_VIOLATION |
InvalidParams |
"Request payload does not conform to schema" |
EXPIRED |
InvalidRequest |
"Event has expired" |
REVOKED |
InvalidRequest |
"Sender key has been revoked" |
NOT_FOUND |
InvalidRequest |
"Resource or schema not found" |
RATE_LIMITED |
InvalidRequest |
"Rate limit exceeded" |
ENDPOINT_UNAVAILABLE |
InternalError |
"XProtocol endpoint unavailable" |
| (upstream MCP error) | InternalError |
Forwarded MCP error message |
6. Identity and Trust Model
6.1 — Adapter Identity
The adapter holds a single Ed25519 + X25519 keypair. This keypair is the cryptographic identity of the adapter instance. All events sent by the adapter are signed with this key.
For a self-hosted enterprise deployment, this key is registered in the organizational key hierarchy:
Organization root key
└── Department key (Engineering)
└── Adapter key (Acme Corp XProtocol Adapter)
├── Wrapped: filesystem MCP server
├── Wrapped: Salesforce CRM MCP server
└── Wrapped: Internal API MCP server
XProtocol clients verifying the adapter's events can walk this chain to confirm the adapter is authorized by the organization. The adapter's key inherits organizational trust.
6.2 — Key Generation
# Generate a new adapter keypair
xprotocol-adapter keygen --output ~/.xprotocol/adapter.key
# Register with parent key (organizational deployment)
xprotocol-adapter register \
--key ~/.xprotocol/adapter.key \
--parent-key ~/.xprotocol/org-dept.key \
--capabilities "filesystem.read,filesystem.write,crm.read"
6.3 — Trust Disclosure
The adapter's xp.endpoint.announce event explicitly declares
which MCP servers it is wrapping:
{
"kind": "xp.endpoint.announce",
"payload": {
"display_name": "Acme Corp XProtocol Adapter",
"adapter_version": "0.1.0",
"mcp_sources": [
{
"name": "filesystem",
"transport": "stdio",
"namespace": "com.acme.filesystem",
"tool_count": 5
},
{
"name": "salesforce-crm",
"transport": "sse",
"url": "https://mcp.salesforce.com/sse",
"namespace": "com.salesforce.crm",
"tool_count": 23
}
],
"xprotocol_sources": [
{
"name": "weather-service",
"endpoint": "xp://weather.example.com",
"tool_count": 3
}
]
}
}
XProtocol clients can inspect this announcement to understand what the adapter is and what it wraps before deciding to trust it.
6.4 — Delegated Identity (Advanced)
For deployments where events should appear to come from the user (not the adapter), the adapter supports delegated identity:
The user's root key signs a delegation event authorizing the adapter to act on their behalf within specified capability limits:
{
"kind": "xp.key.delegate",
"payload": {
"delegated_key": "<adapter_public_key>",
"capabilities": ["filesystem.read", "crm.read"],
"on_behalf_of": "<user_public_key>",
"expires_at": 1717086400
}
}
Events from the adapter with delegated identity carry both the adapter key (sender) and the delegation event reference. Receiving services verify the delegation chain and attribute the action to the delegating user.
7. Schema Registry
7.1 — Local Schema Registry
The adapter maintains a local schema registry populated from:
- MCP tool definitions (fetched via
tools/liston startup and refreshed periodically) - XProtocol schemas from configured
xprotocol_sources - Manual schema overrides from configuration
The registry maps:
- kind → schema contract (for XProtocol lookup)
- mcp_tool_name → MCP server + tool (for MCP lookup)
- mcp_tool_name → kind (for reverse lookup)
7.2 — Schema Refresh
MCP servers may add, remove, or modify tools. The adapter refreshes its schema registry:
- On startup
- Every
schema_refresh_interval_seconds(default: 300) - On receiving an explicit
xp.schema.refreshevent
When a schema changes, the adapter publishes an updated
xp.endpoint.announce event so XProtocol clients can refresh their
cached schema.
7.3 — Schema Publication
The adapter publishes its complete schema catalog via the standard XProtocol discovery mechanism:
GET https://adapter.acme.com/.well-known/xprotocol-endpoint
{
"version": "xp1",
"endpoint": "wss://adapter.acme.com/xp",
"public_key": "ed25519:...",
"schema_url": "https://adapter.acme.com/xp/schemas",
"adapter": true,
"mcp_sources": ["filesystem", "salesforce-crm"],
"xprotocol_sources": ["weather-service"]
}
AI agents discovering this endpoint know immediately it is an adapter, what it wraps, and where to get the complete schema catalog.
8. Security Considerations
8.1 — Trust Boundaries
The adapter is a trust boundary between MCP and XProtocol. It makes a guarantee to XProtocol clients: "events arriving at this adapter's key will be faithfully forwarded to the upstream MCP server." XProtocol clients must trust the adapter operator to uphold this.
This is equivalent to trusting any XProtocol endpoint operator — you trust the key, and the key is published through verified channels (organizational key hierarchy, DNS TXT, well-known URL).
8.2 — MCP Server Authentication
The adapter authenticates to upstream MCP servers using whatever credentials the MCP server requires (bearer tokens, API keys, client certificates). These credentials are stored in the adapter's configuration and never transmitted to XProtocol clients. From the XProtocol client's perspective, the adapter IS the endpoint — the upstream MCP server's authentication model is hidden behind the adapter's XProtocol identity.
8.3 — Capability Enforcement
The adapter enforces XProtocol capability checks before forwarding
any MCP tool call. A key without the required capability receives
an AUTHORIZATION_INSUFFICIENT error — the MCP server never sees
the request. This is additive security: the adapter adds XProtocol's
capability model on top of whatever authentication the MCP server
already has.
8.4 — Rate Limiting
The adapter enforces rate limits per sender key, configurable per MCP source. Rate limits are applied before forwarding — protecting upstream MCP servers from being overwhelmed by XProtocol clients.
8.5 — Schema Poisoning Mitigation
The adapter validates all generated schemas before publishing them. Schemas that reference external URLs, contain recursive structures, or exceed size limits are rejected. This prevents a compromised MCP server from publishing malicious schemas through the adapter.
8.6 — Residual Risk
The adapter is a trusted intermediary. A compromised adapter can: - Forge responses to XProtocol clients - Forward unauthorized requests to MCP servers (if capability checks are bypassed) - Log plaintext payloads before they are encrypted
Mitigation: adapter keys should be registered in organizational key hierarchies with limited delegation scope. Adapter software should be open-source and auditable. Adapter deployments should be logged and monitored.
9. The Adoption Path
The adapter is designed to make XProtocol adoption zero-friction for the existing MCP ecosystem. The adoption journey:
Day 1 — Install adapter
npm install -g @xprotocol/mcp-adapter
xprotocol-adapter keygen
# Create minimal xprotocol-mcp-adapter.yml
xprotocol-adapter start
Result: All existing MCP servers are now XProtocol endpoints.
Any XProtocol client can call them.
No changes to any existing MCP server.
Day 2 — Add XProtocol sources
# Add xprotocol_sources to yml
# Point at XProtocol-native endpoints
Result: Claude Code can now call any XProtocol endpoint as an
MCP tool. Zero new integration code.
Week 1 — Organizational registration
xprotocol-adapter register --parent-key org.key
Result: Adapter gains organizational trust. XProtocol clients
outside the organization can verify the adapter's authority.
Month 1 — First native XProtocol endpoint
# One internal service publishes a native XProtocol schema
# No longer needs the adapter as an intermediary
Result: Direct XProtocol-to-XProtocol communication for one service.
The adapter remains for all other services.
Year 1 — Progressive native migration
# Services migrate to native XProtocol schemas as they are updated
# Adapter handles legacy MCP servers
# Native endpoints handle new XProtocol-first services
Result: Hybrid ecosystem. Some services native, some wrapped.
All accessible from both MCP and XProtocol clients.
No "flag day" migration. No disruption.
10. XProtocol DevServer (Local Dev Bundle)
The DevServer is a single binary for local development and demos. It combines:
- XProtocol MCP Adapter (the full adapter)
- Local XProtocol relay (minimal, in-process)
- Minimal Event Store (SQLite-backed, local only)
- Auto-generated self-signed keypair (dev only)
- Hot reload on config changes
- Pretty-printed event log in terminal
# Install
npm install -g @xprotocol/devserver
# Start with a config file
xprotocol-devserver --config ./xprotocol-mcp-adapter.yml
# Start with inline MCP server (simplest possible demo)
xprotocol-devserver --mcp-command "npx @modelcontextprotocol/server-filesystem /tmp" \
--namespace com.demo.filesystem
# Output:
# ✓ XProtocol DevServer started
# ✓ Adapter key: ed25519:demo1234...
# ✓ Local relay: ws://localhost:8765
# ✓ Wrapped MCP server: com.demo.filesystem (5 tools)
# ✓ Schema catalog: http://localhost:8766/.well-known/xprotocol-endpoint
#
# Paste into Claude Code MCP config:
# { "mcpServers": { "xprotocol": { "command": "xprotocol-devserver", "args": ["--mcp-proxy"] } } }
DevServer is explicitly not for production. It trades clean separation for setup simplicity. The single-binary design makes it ideal for:
- Developer onboarding ("run one command, see XProtocol work")
- Conference demos
- CI/CD test environments
- Local integration testing
11. Conformance
11.1 — Mandatory Behaviors
A conformant XProtocol MCP Adapter MUST:
- Implement the deterministic MCP → XProtocol schema translation algorithm (§4.1) — output must be identical for identical input
- Implement the deterministic XProtocol → MCP tool translation algorithm (§4.2)
- Auto-generate
semanticannotations for all wrapped MCP tools (§4.6) - Compute and publish
description_quality_scorefor all schemas (§4.6) - Flag low-quality schemas in
xp.endpoint.announce(§4.6) - Implement
xp.schema.describefor Phase 1 agent discovery (§4.6) - Enforce XProtocol capability checks before forwarding to MCP servers
- Verify Ed25519 signatures on all incoming XProtocol events
- Sign all outgoing XProtocol events with the adapter's key
- Encrypt all outgoing XProtocol event payloads
- Publish a conformant
xp.endpoint.announceevent includingmcp_sourcesdisclosure - Auto-compile GBNF grammars for all wrapped MCP tool schemas
11.2 — Optional Behaviors
A conformant adapter MAY:
- Support delegated identity (§6.4)
- Support MCP resources and prompts translation (§4.5)
- Support schema refresh intervals (§7.2)
- Support managed service deployment model
- Support the DevServer bundle (§10)
11.3 — Conformance Test Suite
The adapter conformance test suite verifies:
- Schema translation is deterministic — same input produces same output
semanticfield is auto-generated for every wrapped tooldescription_quality_scoreis computed and present on every schemaxp.schema.describereturns ranked matches for intent queries- Low-quality schemas are flagged in
xp.endpoint.announce - Capability enforcement — requests without required capability are rejected
- Error translation — XProtocol errors map to correct MCP errors
- Signature verification — invalid signature events are rejected
- Trust disclosure —
xp.endpoint.announceincludesmcp_sources - Bidirectionality — both directions work simultaneously
- GBNF compilation — all schemas produce valid parseable grammars
Appendix A — CLI Reference
# Generate keypair
xprotocol-adapter keygen [--output path]
# Register with parent key
xprotocol-adapter register --key path --parent-key path --capabilities csv
# Start adapter
xprotocol-adapter start [--config path] [--port 8765]
# Validate configuration
xprotocol-adapter validate --config path
# List wrapped schemas
xprotocol-adapter schemas --config path
# Test a specific MCP server connection
xprotocol-adapter test-mcp --config path --source name
# Show adapter status
xprotocol-adapter status
Appendix B — Schema Translation Reference
Complete field mapping tables for both translation directions, including edge cases for optional fields, array types, nested objects, and schema composition (allOf, anyOf, oneOf).
Array type handling
MCP tools with array input parameters:
{ "type": "array", "items": { "type": "string" } }
Translates to XProtocol schema (plural-only form mandate):
{ "type": "array", "items": { "type": "string" }, "minItems": 0 }
GBNF compilation for arrays:
string-array ::= "[" ws (string ("," ws string)*)? ws "]"
Nested object handling
Nested objects translate directly — JSON Schema is JSON Schema in both MCP and XProtocol. No transformation needed beyond namespace scoping of the enclosing schema.
Schema version tracking
When an MCP server's tool definition changes, the adapter increments the schema version:
v1.0.0 → initial translation
v1.0.1 → description changed (non-breaking)
v1.1.0 → new optional field added (non-breaking)
v2.0.0 → required field added or removed (breaking)
Breaking changes trigger a new xp.endpoint.announce event so
XProtocol clients can refresh their cached schemas and GBNF grammars.
XProtocol.ai is an independent open protocol project and is not affiliated with, endorsed by, or connected to XProtocol.org or any related entities.