systemprompt-mcp
Model Context Protocol server registry and tool execution
On this page
Model Context Protocol implementation providing server registry, tool execution, and HTTP-native transports.
Overview
The MCP crate implements the Model Context Protocol, enabling AI clients like Claude Desktop and ChatGPT to interact with SystemPrompt's tool servers. It handles server lifecycle, tool discovery, and authenticated execution.
Layer Position
Domain Layer
├── systemprompt-users
├── systemprompt-oauth
├── systemprompt-mcp ← You are here
├── systemprompt-ai
└── ...
Depends on: systemprompt-database, systemprompt-security, systemprompt-events Used by: systemprompt-api, systemprompt-agent
Key Features
- HTTP-native transports - Streamable HTTP, SSE
- OAuth2 authentication - Per-tool permission scopes
- Server registry - Dynamic server management
- Tool execution - Type-safe tool calls
- Resource providers - Content and file resources
Configuration
Define MCP servers in services/mcp/:
# services/mcp/content.yaml
name: content
description: Content management tools
binary: mcp-content
transport:
type: streamable-http
endpoint: "/api/v1/mcp/content/mcp"
oauth:
required: true
scopes: ["content:read", "content:write"]
audience: ["systemprompt"]
tools:
- name: search_content
description: Search for content by query
parameters:
query:
type: string
required: true
limit:
type: integer
default: 10
- name: create_content
description: Create new content
parameters:
title:
type: string
required: true
body:
type: string
required: true
Public API
McpRegistry
Server registry for managing MCP servers:
use systemprompt_mcp::{McpRegistry, McpServer};
// Get registry from context
let registry = ctx.mcp_registry.clone();
// List all servers
let servers = registry.list_servers().await?;
// Get specific server
let server = registry.get_server("content").await?;
// Register new server
registry.register(McpServer {
name: "custom".into(),
endpoint: "/api/v1/mcp/custom/mcp".into(),
// ...
}).await?;
Tool Execution
use systemprompt_mcp::{ToolCall, ToolResult};
// Execute a tool
let result = registry.execute_tool(ToolCall {
server: "content".into(),
tool: "search_content".into(),
arguments: serde_json::json!({
"query": "rust tutorial",
"limit": 5
}),
}).await?;
match result {
ToolResult::Success(value) => println!("Result: {}", value),
ToolResult::Error(err) => println!("Error: {}", err),
}
Resource Access
use systemprompt_mcp::ResourceProvider;
// List resources
let resources = provider.list_resources().await?;
// Read resource
let content = provider.read_resource("content://posts/123").await?;
HTTP Endpoints
The MCP crate exposes these endpoints:
| Endpoint | Method | Description |
|---|---|---|
/api/v1/mcp/registry |
GET | List all MCP servers |
/api/v1/mcp/{server}/mcp |
POST | MCP message endpoint |
/api/v1/mcp/{server}/sse |
GET | SSE transport |
Claude Desktop Integration
Configure Claude Desktop to use SystemPrompt MCP servers:
{
"mcpServers": {
"content": {
"url": "https://your-tenant.systemprompt.io/api/v1/mcp/content/mcp",
"transport": "streamable-http",
"headers": {
"Authorization": "Bearer YOUR_TOKEN"
}
}
}
}
Building MCP Servers
Create a new MCP server in extensions/mcp/:
use systemprompt_mcp::{McpServer, Tool, ToolHandler};
pub struct ContentServer;
impl McpServer for ContentServer {
fn name(&self) -> &str { "content" }
fn tools(&self) -> Vec<Tool> {
vec![
Tool::new("search_content")
.description("Search for content")
.parameter("query", ParameterType::String, true),
]
}
}
#[async_trait]
impl ToolHandler for ContentServer {
async fn handle(&self, call: ToolCall) -> Result<ToolResult> {
match call.tool.as_str() {
"search_content" => {
let query = call.get_string("query")?;
let results = search(&query).await?;
Ok(ToolResult::Success(serde_json::to_value(results)?))
}
_ => Err(McpError::UnknownTool),
}
}
}
Related Crates
- systemprompt-agent - Agent-to-agent protocol
- systemprompt-ai - LLM integration
- systemprompt-security - OAuth2 for MCP