This App Registry documentation is in preview and is not production-ready.
Cookbook: Register MCP Server
MCP integration is new and evolving. Configuration format may change as MCP specification updates. See modelcontextprotocol.io for latest MCP spec.
Register your Model Context Protocol (MCP) server to enable AI agents to discover and interact with your service.
What is MCP?
Model Context Protocol is a standard for AI agents to interact with external tools and data sources. It allows agents to:
- Call functions (tools)
- Access data (resources)
- Use pre-configured prompts
- Authenticate securely
Learn more: modelcontextprotocol.io
Prerequisites
- Running MCP server
- MCP configuration (tools, resources, prompts)
- Web3 wallet with testnet OMA tokens
- Domain with DID document (for did:web)
Quick Start Example
1. MCP Server Setup
Basic MCP server (Node.js):
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
const server = new Server({
name: 'example-mcp-server',
version: '1.0.0'
}, {
capabilities: {
tools: {},
resources: {},
prompts: {}
}
});
// Define tools
server.setRequestHandler('tools/list', async () => ({
tools: [
{
name: 'search_knowledge_base',
description: 'Search the knowledge base',
inputSchema: {
type: 'object',
properties: {
query: { type: 'string' }
},
required: ['query']
}
}
]
}));
// Define resources
server.setRequestHandler('resources/list', async () => ({
resources: [
{
uri: 'file:///docs',
name: 'Documentation',
mimeType: 'text/markdown'
}
]
}));
// Start server
const transport = new StdioServerTransport();
await server.connect(transport);
2. Create MCP Metadata
Prepare your MCP configuration for OMATrust. MCP configuration is placed inside the endpoints array:
{
"endpoints": [
{
"name": "MCP",
"endpoint": "https://mcp.example.com",
"tools": [
{
"name": "search_knowledge_base",
"description": "Search the knowledge base for information",
"inputSchema": {
"type": "object",
"properties": {
"query": { "type": "string", "description": "Search query" }
},
"required": ["query"]
}
},
{
"name": "get_documentation",
"description": "Retrieve documentation for a specific topic",
"inputSchema": {
"type": "object",
"properties": {
"topic": { "type": "string" }
}
}
}
],
"resources": [
{
"uri": "file:///docs",
"name": "Documentation",
"description": "Product documentation and guides",
"mimeType": "text/markdown"
},
{
"uri": "https://api.example.com/data",
"name": "API Data",
"description": "Real-time API data feed"
}
],
"prompts": [
{
"name": "explain_feature",
"description": "Explain a product feature to users",
"arguments": [
{
"name": "feature",
"description": "Feature name",
"required": true
}
]
}
],
"transport": {
"http": {
"url": "https://mcp.example.com",
"method": "POST"
}
},
"authentication": {
"oauth2": {
"authorizationUrl": "https://auth.example.com/oauth/authorize",
"tokenUrl": "https://auth.example.com/oauth/token"
}
}
}
]
}
3. Register via Wizard
Step 1 - Verification:
- Name: "Example MCP Server"
- Version: "1.0.0"
- DID:
did:web:mcp.example.com - Interfaces: ☑ API
- API Type: MCP Server
- Verify DID
Step 2 - On-Chain:
- Traits:
api:mcp(auto-added),ai,knowledge-base
Step 3 - Common:
- Description: "MCP server providing knowledge base search and documentation access for AI agents"
- Publisher: "Example Corp"
Step 7 - API Config:
- Click "+ Add Endpoint"
- Name: "MCP"
- Endpoint URL:
https://mcp.example.com - Schema URL:
https://mcp.example.com/schema.json(optional)
MCP Configuration (inside endpoint):
- Click "+ Add Tool" for each tool
- Name:
search_knowledge_base - Description: "Search the knowledge base"
- Input Schema:
{"type": "object", ...}
- Name:
- Click "+ Add Resource" for each resource
- URI:
file:///docs - Name: "Documentation"
- URI:
- Click "+ Add Prompt" for each prompt
- Configure transport & authentication (JSON mode)
- Interface Versions:
1.0
Step 6 - Review & Submit
4. Test Discovery
AI agents can now find your MCP server:
# Python AI agent example
import requests
from web3 import Web3
def discover_mcp_servers():
# Search OMATrust for MCP servers
registry_api = "https://registry.omatrust.org/api"
# Get services with api:mcp trait
response = requests.get(f"{registry_api}/search", params={
'traits': 'api:mcp',
'interface': 2
})
servers = []
for service in response.json()['results']:
# Fetch metadata
metadata = requests.get(service['dataUrl']).json()
# Find MCP endpoint
mcp_endpoint = next((ep for ep in metadata.get('endpoints', []) if ep.get('name') == 'MCP'), None)
if mcp_endpoint:
servers.append({
'name': metadata['name'],
'endpoint': mcp_endpoint['endpoint'],
'tools': [t['name'] for t in mcp_endpoint.get('tools', [])],
'did': service['did']
})
return servers
# Discover and use
servers = discover_mcp_servers()
print(f"Found {len(servers)} MCP servers")
for server in servers:
print(f"\n{server['name']}")
print(f" Endpoint: {server['endpoint']}")
print(f" Tools: {', '.join(server['tools'])}")
Advanced: Dynamic MCP Configuration
Generate Config from Code
// Auto-generate MCP config from your server
import { inspect } from 'util';
function generateMcpConfig(server: any) {
const tools = server.getTools().map(tool => ({
name: tool.name,
description: tool.description,
inputSchema: tool.schema
}));
const resources = server.getResources().map(resource => ({
uri: resource.uri,
name: resource.name,
description: resource.description,
mimeType: resource.mimeType
}));
return {
tools,
resources,
prompts: server.getPrompts(),
transport: server.transportConfig,
authentication: server.authConfig
};
}
// Use in registration
const mcpConfig = generateMcpConfig(myServer);
// Paste into wizard or use programmatic registration
Update When Tools Change
// When you add new tools to your MCP server
async function updateMcpMetadata(newTools: Tool[]) {
const currentMetadata = await fetchMetadata(service.dataUrl);
// Update MCP tools in endpoints array
const mcpEndpoint = currentMetadata.endpoints.find(ep => ep.name === 'MCP');
if (mcpEndpoint) {
mcpEndpoint.tools = newTools;
}
const updatedMetadata = {
...currentMetadata
};
// Compute new hash
const jsonString = JSON.stringify(updatedMetadata);
const newHash = ethers.id(jsonString);
const newDataUrl = `https://your-domain.com/api/data-url/${did}/v/${major}.${minor}.${patch + 1}`;
// Update on-chain (includes metadata atomically)
await registry.updateAppControlled(
did,
major,
newDataUrl,
newHash,
0, // keccak256
0, // interfaces (no change)
[], // traitHashes (no change)
minor,
patch + 1, // Increment patch
jsonString // Metadata stored atomically
);
}
Authentication Patterns
OAuth2 for MCP
{
"mcp": {
"authentication": {
"oauth2": {
"authorizationUrl": "https://auth.example.com/oauth/authorize",
"tokenUrl": "https://auth.example.com/oauth/token",
"scopes": ["read:data", "write:data"]
}
}
}
}
Blockchain Auth
{
"mcp": {
"authentication": {
"blockchain": {
"chainId": "eip155:1",
"contractAddress": "0x123...",
"requiredNFT": true
}
}
}
}
Tool Best Practices
Well-Defined Input Schemas
{
"name": "analyze_sentiment",
"description": "Analyze sentiment of text using ML model",
"inputSchema": {
"type": "object",
"properties": {
"text": {
"type": "string",
"description": "Text to analyze",
"maxLength": 5000
},
"language": {
"type": "string",
"enum": ["en", "es", "fr", "de"],
"default": "en",
"description": "Language of the text"
}
},
"required": ["text"]
},
"annotations": {
"rateLimit": "100/hour",
"cost": "0.001 OMA per call"
}
}
Error Handling
{
"name": "get_weather",
"description": "Get current weather for a location",
"inputSchema": { ... },
"annotations": {
"errors": {
"INVALID_LOCATION": "Location not found in database",
"API_LIMIT_EXCEEDED": "Rate limit exceeded - try again later",
"SERVICE_UNAVAILABLE": "Weather API temporarily unavailable"
}
}
}
Resource Patterns
Static Resources
{
"uri": "file:///data/products.json",
"name": "Product Catalog",
"description": "Complete product catalog with prices and availability",
"mimeType": "application/json"
}
Dynamic Resources
{
"uri": "https://api.example.com/realtime/stock-prices",
"name": "Stock Prices",
"description": "Real-time stock price feed",
"mimeType": "application/json",
"annotations": {
"updateFrequency": "1s",
"authentication": "required"
}
}
Prompt Engineering
Pre-configured Prompts
{
"prompts": [
{
"name": "product_recommendation",
"description": "Generate personalized product recommendations",
"arguments": [
{
"name": "user_preferences",
"description": "User's stated preferences",
"required": true
},
{
"name": "budget",
"description": "Maximum budget",
"required": false
}
]
},
{
"name": "technical_support",
"description": "Provide technical support for common issues",
"arguments": [
{
"name": "problem_description",
"description": "Description of the technical issue"
}
]
}
]
}
Monitoring MCP Servers
Health Checks
async function checkMcpHealth(did: string) {
const service = await getService(did, 1);
const metadata = await fetchMetadata(service.dataUrl);
// Ping endpoint
const healthy = await fetch(metadata.endpoint.url)
.then(r => r.ok)
.catch(() => false);
// Verify tools are accessible
const toolsWork = await testMcpTools(metadata.endpoint.url, metadata.mcp.tools);
return {
endpointHealthy: healthy,
toolsHealthy: toolsWork,
overall: healthy && toolsWork
};
}
Usage Analytics
Track which agents use your MCP server:
// Log in your MCP server
server.onToolCall((tool, params, agentDid) => {
analytics.log({
timestamp: Date.now(),
tool: tool.name,
agentDid,
success: true
});
});
// Aggregate stats
const stats = {
totalCalls: 15234,
uniqueAgents: 42,
mostUsedTool: 'search_knowledge_base',
avgResponseTime: 245 // ms
};
Versioning MCP Servers
Interface Versions
{
"interfaceVersions": ["1.0", "1.1"],
"mcp": {
"tools": [
// v1.0 tools
{ "name": "search", ... },
// v1.1 added tool
{ "name": "advanced_search", ... }
]
}
}
Backward Compatibility
Strategy:
- Add new tools (don't remove old ones)
- Increment interface version
- Document changes in schema URL
- Agents can check
interfaceVersionsand use appropriate tools
Security Considerations
Validate Agent Identity
// In your MCP server
server.onRequest(async (request, agentInfo) => {
// Verify agent is registered in OMATrust
const agentService = await getService(agentInfo.did, 1);
const verified = await checkAttestations(agentInfo.did, agentService.minter, agentService.dataHash);
if (!verified.ownerVerified) {
throw new Error('Agent not verified - request denied');
}
// Process request
return handleRequest(request);
});
Rate Limiting by Agent
const agentRateLimits = new Map();
function checkRateLimit(agentDid: string): boolean {
const limit = agentRateLimits.get(agentDid) || { count: 0, resetAt: Date.now() + 3600000 };
if (Date.now() > limit.resetAt) {
limit.count = 0;
limit.resetAt = Date.now() + 3600000;
}
if (limit.count >= 1000) {
return false; // Limit exceeded
}
limit.count++;
agentRateLimits.set(agentDid, limit);
return true;
}
Complete Registration Example
DID Document
https://mcp.example.com/.well-known/did.json:
{
"@context": ["https://www.w3.org/ns/did/v1"],
"id": "did:web:mcp.example.com",
"verificationMethod": [
{
"id": "did:web:mcp.example.com#owner",
"type": "EcdsaSecp256k1VerificationKey2019",
"controller": "did:web:mcp.example.com",
"blockchainAccountId": "eip155:66238:0xYourWalletAddress"
}
]
}
Registration Wizard
Step 1:
- Name: "Knowledge Base MCP Server"
- Version: "1.0.0"
- DID:
did:web:mcp.example.com - Interfaces: ☑ API
- API Type: MCP Server
Step 2:
- Traits:
api:mcp(auto),ai,knowledge-base,search
Step 3:
- Description: "MCP server providing AI agents access to our knowledge base"
- Publisher: "Example Corp"
- External URL:
https://example.com/mcp - Support URL:
https://example.com/mcp/docs
Step 7 - MCP Config:
- Endpoint URL:
https://mcp.example.com - Schema URL:
https://mcp.example.com/schema.json - Interface Versions:
1.0
Add Tools: (2 tools)
- search_knowledge_base
- get_documentation
Add Resources: (2 resources)
- file:///docs
- https://api.example.com/data
Add Prompts: (1 prompt)
- explain_feature
Transport & Auth:
{
"transport": {"http": {"url": "https://mcp.example.com"}},
"authentication": {"oauth2": {...}}
}
Submit!
Final Metadata
{
"name": "Knowledge Base MCP Server",
"description": "MCP server providing AI agents access to our knowledge base",
"publisher": "Example Corp",
"external_url": "https://example.com/mcp",
"supportUrl": "https://example.com/mcp/docs",
"endpoints": [
{
"name": "MCP",
"endpoint": "https://mcp.example.com",
"schemaUrl": "https://mcp.example.com/schema.json",
"interfaceVersions": ["1.0"],
"tools": [...],
"resources": [...],
"prompts": [...],
"transport": {...},
"authentication": {...}
}
],
"traits": ["api:mcp", "ai", "knowledge-base", "search"]
}
AI Agent Integration
Claude Desktop
AI agents using Claude Desktop can discover your server:
// claude_desktop_config.json
{
"mcpServers": {
"example-kb": {
"command": "node",
"args": ["/path/to/mcp-client.js"],
"env": {
"MCP_SERVER_DID": "did:web:mcp.example.com",
"OMATRUST_REGISTRY": "https://registry.omatrust.org"
}
}
}
}
Client discovers server:
// mcp-client.js
const { getService, fetchMetadata } = require('./omatrust-sdk');
async function main() {
const did = process.env.MCP_SERVER_DID;
// Fetch MCP server metadata
const service = await getService(did, 1);
const metadata = await fetchMetadata(service.dataUrl);
// Find MCP endpoint
const mcpEndpoint = metadata.endpoints.find(ep => ep.name === 'MCP');
if (!mcpEndpoint) throw new Error('No MCP endpoint found');
// Connect to MCP server
const mcpClient = new MCPClient(mcpEndpoint.endpoint);
await mcpClient.connect(mcpEndpoint);
// Now Claude can use the tools
console.log(`Connected to ${metadata.name}`);
console.log(`Available tools: ${metadata.mcp.tools.map(t => t.name).join(', ')}`);
}
main();
Custom AI Agent
import requests
from mcp import Client
async def connect_to_omatrust_mcp(did: str):
# Get server info from OMATrust
service = get_service_from_omatrust(did)
metadata = requests.get(service['dataUrl']).json()
# Verify before connecting
verified = verify_service(service)
if not verified['ownerVerified']:
raise Exception(f"MCP server {did} not verified")
# Find MCP endpoint
mcp_endpoint = next((ep for ep in metadata.get('endpoints', []) if ep.get('name') == 'MCP'), None)
if not mcp_endpoint:
raise Exception(f"No MCP endpoint found for {did}")
# Connect using MCP SDK
client = Client(mcp_endpoint['endpoint'])
await client.initialize()
# List available tools
tools = await client.list_tools()
print(f"Connected to {metadata['name']}")
print(f"Tools: {[t.name for t in tools]}")
return client
# Use the server
client = await connect_to_omatrust_mcp('did:web:mcp.example.com')
result = await client.call_tool('search_knowledge_base', {'query': 'What is OMATrust?'})
Monetization with x402
Paid MCP Server
{
"mcp": { ... },
"payments": [
{
"type": "x402",
"url": "https://mcp.example.com/x402",
"chains": ["eip155:1", "eip155:10"]
}
],
"traits": ["api:mcp", "pay:x402", "premium"]
}
Agents check pricing before using:
metadata = requests.get(service['dataUrl']).json()
if 'pay:x402' in metadata.get('traits', []):
# Check pricing
pricing = requests.get(metadata['payments'][0]['url'] + '/supported').json()
print(f"Cost per tool call: {pricing['perRequest']}")
# Agent decides if cost is acceptable
if pricing['perRequest'] < max_acceptable_cost:
# Proceed with payment
connect_with_payment(metadata)
Testing Your Registration
Verify Metadata
# Fetch your metadata
curl https://registry.omatrust.org/api/data-url/did:web:mcp.example.com/v/1.0 | jq '.'
# Should see:
# - mcp object with tools/resources/prompts
# - endpoint.url pointing to your server
# - traits including api:mcp
Test with MCP Client
# Use MCP inspector
npx @modelcontextprotocol/inspector \
--server https://mcp.example.com
# Should connect and list your tools
Troubleshooting
"MCP configuration invalid"
- Check JSON syntax in tool inputSchemas
- Ensure all required fields present (name, description)
- Validate against MCP spec
"Tools not appearing for agents"
- Verify endpoint is accessible
- Check CORS headers (if HTTP transport)
- Ensure authentication works
"Metadata too large"
- MCP configs can be large (tools, resources, prompts)
- Use custom dataUrl hosting (not on-chain)
- Keep inputSchemas concise
Next Steps
- Register A2A Agent - Agent-to-agent protocol
- Client Guide - Query MCP servers
- MCP Specification: modelcontextprotocol.io
Have an MCP server? Register it at registry.omatrust.org to make it discoverable by AI agents!