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-sdk

rcp-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