Getting started
Install rcp-sdk, expose one tool from a server, and call it from a client — end to end. Works with OpenAI, LangChain & Gemini.
Install
shell
npm install rcp-sdkrcp-sdk ships two entry points — import whichever role you’re building.
typescript
// Building the AI application? Import the client.
import { createRcpClient } from 'rcp-sdk/client';
// Exposing your own REST endpoints as tools? Import the server helper.
import { defineTool } from 'rcp-sdk/server';1. Define a tool on the server
defineTool() never touches the network — it returns a plain object. Serving it is up to you: collect your tools into an array and return them from whatever route your server already has.
server.ts
import { defineTool } from 'rcp-sdk/server';
import { z } from 'zod';
export const getWeather = defineTool({
name: 'get_weather',
description: 'Get current weather information for a city.',
method: 'GET',
args: z.object({
city: z.string().describe('City name, e.g. "Paris"'),
}),
url: 'https://internal.example.com/weather',
queryParams: { city: (t) => t.arg('city') },
responseMappings: {
temperatureC: '@temperatureC',
conditions: '@conditions',
},
});2. Serve the manifest
Return { rcpVersion, auth, tools } from a single route — a plain Node http server is a fully conformant example, no framework required.
server.ts (continued)
import { createServer } from 'node:http';
const manifest = {
rcpVersion: '0.1',
auth: { type: 'header', header: 'Authorization', scheme: 'Bearer' },
tools: [getWeather],
};
createServer((req, res) => {
if (req.url === '/manifest') {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify(manifest));
return;
}
// ...the /weather route the tool's url points at
}).listen(4310);3. Discover and call it from a client
client.ts
import { createRcpClient } from 'rcp-sdk/client';
const client = createRcpClient({
auth: { type: 'header', secret: process.env.SERVER_TOKEN! },
});
const { manifest, tools } = await client.discover('http://localhost:4310/manifest');
console.log(`Discovered ${tools.length} tool(s) from manifest v${manifest.rcpVersion}`);
const weather = tools.find((t) => t.name === 'get_weather')!;
const result = await client.call(weather, { city: 'Paris' });
console.log(result.mapped);
// { temperatureC: 18, conditions: 'Partly cloudy' }discover() returns each tool’s exposedParams alongside its raw params — show exposedParams to your model, since that’s the list with any resolver-bound params already stripped out. See Resolvers.That’s the whole loop. For a real-world Express + OpenAI tool-calling walkthrough, or the smallest possible runnable version with no framework at all, see RCP examples — Express + OpenAI demo.
Next steps
- RCP vs MCP — lightweight alternative for AI agents — decide if stateless HTTP fits vs a dedicated protocol server
- Build AI agent with OpenAI tools — via OpenAI SDK adapter —
rcpToolsToOpenAiTools()foropenai.chat.completions.create() - Build AI agent with LangChain — DynamicStructuredTool + LangGraph
- Build AI agent with Gemini — Google GenAI function calling
- Understand the RCP manifest format — JSON directory of AI tools
- Secure tenant ID from LLM with resolvers