MCP
This content is for the 0.6.3 version. Switch to the latest version for up-to-date documentation.
Overview
MCP services expose Model Context Protocol servers that AI agents can connect to and use. These services provide tools, prompts, and resources that AI models can access through standardized interfaces.
Models deployed on Raindrop that support native tool calling can directly use these MCP servers. External AI agents and services can also connect to your MCP servers using the standard protocol. You can create both public MCP services for open access and protected MCP services that require OAuth authentication. The framework handles connection management, type safety through Zod schemas, and automatic registration of tools, prompts, and resources.
Creating
Define MCP services in your raindrop.manifest using either public or protected visibility:
application "demo-app" { mcp_service "demo-mcp" { visibility = "public" }}
application "demo-app" { mcp_service "demo-mcp" { visibility = "protected" authorization_server = "https://authkit.liquidmetal.run" }}
Implementing
Build your MCP service by registering tools, prompts, and resources:
export default { async fetch(request: Request, env: Env): Promise<Response> { // Get the MCP server instance from environment const mcpServer = env.DEMO_MCP;
// Register a simple tool with description and schema mcpServer.registerTool("greet", { description: "Greet a user by name", inputSchema: { name: z.string() } }, async (args, extra) => { return { text: `Hello, ${args.name}!` }; });
return new Response("MCP service configured"); }};
Core Concepts
MCP services expose three types of capabilities that AI agents can interact with:
- Tools: Functions that AI agents can call with typed parameters
- Prompts: Reusable prompt templates with variable substitution
- Resources: Data sources that agents can read from
Tools
Tools are functions that AI agents can execute. Each tool has a name, description, and optional schema for parameters:
// Register a tool without parametersmcpServer.registerTool("get_time", { description: "Get the current time"}, async (args, extra) => { return { time: new Date().toISOString() };});
// Register a tool with parametersmcpServer.registerTool("calculate", { description: "Perform calculation", inputSchema: { operation: z.enum(["add", "multiply"]), numbers: z.array(z.number()) }}, async (args, extra) => { const result = args.operation === "add" ? args.numbers.reduce((a, b) => a + b, 0) : args.numbers.reduce((a, b) => a * b, 1); return { result };});
Prompts
Prompts provide reusable templates that AI agents can use with dynamic content:
// Register a prompt templatemcpServer.registerPrompt("code_review", { description: "Generate code review", argsSchema: { language: z.string(), code: z.string() }}, async (args, extra) => { return { messages: [{ role: "user", content: `Review this ${args.language} code:\n${args.code}` }] };});
Resources
Resources expose data that AI agents can read:
// Register a static resourcemcpServer.registerResource("config", "file://config.json", { description: "Application configuration", mimeType: "application/json"}, async (uri, extra) => { const config = await loadConfig(); return { contents: [{ text: JSON.stringify(config, null, 2), mimeType: "application/json" }] };});
registerTool
Register a tool with a configuration object. Provides more control over tool metadata including title, schemas, and annotations.
registerTool<InputArgs extends ZodRawShape, OutputArgs extends ZodRawShape>( name: string, config: { title?: string; description?: string; inputSchema?: InputArgs; outputSchema?: OutputArgs; annotations?: Record<string, unknown>; }, cb: ToolCallback<InputArgs>): RegisteredTool;
RegisteredTool
Example
Register a weather tool with detailed configuration:
// Register a weather tool with full configurationconst weatherTool = mcpServer.registerTool("get-weather", { title: "Get Weather Information", description: "Fetch current weather conditions and forecast", inputSchema: { location: z.string().describe("City name or coordinates"), units: z.enum(["celsius", "fahrenheit"]).optional(), includeForecast: z.boolean().optional() }, outputSchema: { temperature: z.number(), conditions: z.string(), forecast: z.array(z.object({ day: z.string(), high: z.number(), low: z.number() })).optional() }, annotations: { category: "weather", rateLimit: "100/hour" }}, async (args, extra) => { const weather = await fetchWeatherAPI(args.location, args.units); return { temperature: weather.temp, conditions: weather.description, forecast: args.includeForecast ? weather.forecast : undefined };});
registerPrompt
Register a prompt template with a configuration object. Provides structured control over prompt metadata.
registerPrompt<Args extends PromptArgsRawShape>( name: string, config: { title?: string; description?: string; argsSchema?: Args; }, cb: PromptCallback<Args>): RegisteredPrompt;
RegisteredPrompt
Example
Register a documentation prompt with configuration:
// Register a documentation prompt with configurationconst docPrompt = mcpServer.registerPrompt("generate-docs", { title: "Documentation Generator", description: "Generate comprehensive documentation for code", argsSchema: { codeType: z.enum(["function", "class", "module"]), language: z.string(), includeExamples: z.boolean().default(true), style: z.enum(["brief", "detailed"]).optional() }}, async (args, extra) => { const template = args.style === "brief" ? "Generate concise documentation" : "Generate detailed documentation with examples";
return { messages: [{ role: "system", content: `You are a documentation expert for ${args.language} code.` }, { role: "user", content: { type: "text", text: `${template} for this ${args.codeType}. ${args.includeExamples ? "Include usage examples." : ""}` } }] };});
registerResource
Register a resource with a configuration object. Provides structured control over resource metadata.
registerResource( name: string, uriOrTemplate: string | ResourceTemplate, config: ResourceMetadata, readCallback: ReadResourceCallback | ReadResourceTemplateCallback): RegisteredResource | RegisteredResourceTemplate;
RegisteredResource | RegisteredResourceTemplate
Example
Register a database resource with configuration:
// Register a database resource with configurationconst dbResource = mcpServer.registerResource( "database-stats", "db://stats", { description: "Database performance and usage statistics", mimeType: "application/json", metadata: { refreshInterval: 30000, cacheable: true } }, async (uri, extra) => { const stats = await queryDatabaseStats();
return { contents: [{ uri: uri.toString(), mimeType: "application/json", text: JSON.stringify({ connections: stats.activeConnections, queries: stats.queryCount, performance: stats.avgResponseTime, timestamp: new Date().toISOString() }, null, 2) }] }; });