Skip to content

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"
}
}

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 parameters
mcpServer.registerTool("get_time", {
description: "Get the current time"
}, async (args, extra) => {
return { time: new Date().toISOString() };
});
// Register a tool with parameters
mcpServer.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 template
mcpServer.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 resource
mcpServer.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;

Example

Register a weather tool with detailed configuration:

// Register a weather tool with full configuration
const 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;

Example

Register a documentation prompt with configuration:

// Register a documentation prompt with configuration
const 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;

Example

Register a database resource with configuration:

// Register a database resource with configuration
const 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)
}]
};
}
);