Examples
End-to-end samples in plain Node.js. The same calls work from any language that can speak HTTPS + JSON.
A. List a user's top links
import fetch from 'node-fetch';
const MCP = 'https://mcp.shuuka.com/';
const TOKEN = process.env.SHUUKA_ACCESS_TOKEN;
async function call(method, params = {}, idempotencyKey) {
const headers = {
'Authorization': `Bearer ${TOKEN}`,
'Content-Type': 'application/json',
};
if (idempotencyKey) headers['Idempotency-Key'] = idempotencyKey;
const res = await fetch(MCP, {
method: 'POST',
headers,
body: JSON.stringify({
jsonrpc: '2.0',
id: Date.now(),
method,
params,
}),
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
return res.json();
}
const result = await call('tools/call', {
name: 'get_top_links',
arguments: { limit: 5 },
});
console.log(result.result.structuredContent.links);
B. Update a profile (write tool — needs Idempotency-Key)
import { randomUUID } from 'crypto';
const idempotencyKey = randomUUID();
const result = await call(
'tools/call',
{
name: 'update_my_profile',
arguments: {
bio: 'On tour — Berlin May 14, Paris May 17.',
},
},
idempotencyKey
);
if (result.error?.code === 'step_up_required') {
console.log('Send the user to:', result.error.data.auth_url);
} else {
console.log('Updated:', result.result.structuredContent);
}
Per-locale bio (multi-language profile)
To update a translation shown only when a visitor opens the profile with ?lang=<locale>, pass locale. To update the default bio (the fallback rendered when no translation matches the visitor's locale), omit it. To delete a translation, pass an empty bio together with the locale.
// Set the German translation
await call('tools/call', {
name: 'update_my_profile',
arguments: {
bio: 'Ich baue Shuuka — die Plattform für digitale Identität.',
locale: 'de',
},
}, randomUUID());
// Enable German in the profile language switcher (call once)
await call('tools/call', {
name: 'add_my_language',
arguments: { locale: 'de' },
}, randomUUID());
// Make German the primary (default) language
await call('tools/call', {
name: 'set_primary_language',
arguments: { locale: 'de' },
}, randomUUID());
C. Brand-safety verify (Tier 1 — no user grant required)
const result = await call('tools/call', {
name: 'verify_account',
arguments: { handle: 'example.brand', entity: 'Example Inc.' },
});
const v = result.result.structuredContent;
console.log({
is_official: v.is_official,
verified_since: v.verified_since,
networks: v.verified_networks,
});
D. Enterprise — rank a managed roster
const ranked = await call('tools/call', {
name: 'rank_accounts',
arguments: {
metric: 'identity_score',
direction: 'desc',
limit: 10,
},
});
ranked.result.structuredContent.accounts.forEach((acc, i) => {
console.log(`${i + 1}. ${acc.handle} — score ${acc.identity_score}`);
});
E. Subscribe to webhooks for fake reports
import { randomUUID } from 'crypto';
const sub = await call(
'tools/call',
{
name: 'subscribe_webhook',
arguments: {
url: 'https://my-app.example/shuuka/webhook',
events: ['report.created', 'risk.score_changed'],
description: 'Brand-safety alerts',
},
},
randomUUID()
);
const { id, secret } = sub.result.structuredContent;
console.log('Webhook id:', id);
// STORE THIS — shown only once:
console.log('Secret:', secret);
Then handle deliveries:
import express from 'express';
import crypto from 'crypto';
const app = express();
app.use(express.raw({ type: 'application/json' }));
const SECRET = process.env.SHUUKA_WEBHOOK_SECRET;
app.post('/shuuka/webhook', (req, res) => {
const sig = req.headers['x-shuuka-signature'] || '';
const parts = Object.fromEntries(sig.split(',').map(p => p.split('=')));
const t = parseInt(parts.t, 10);
if (!t || Math.abs(Date.now() / 1000 - t) > 300) return res.sendStatus(400);
const expected = crypto
.createHmac('sha256', SECRET)
.update(`${t}.${req.body}`)
.digest('hex');
if (!crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1 || ''))) {
return res.sendStatus(401);
}
const event = JSON.parse(req.body);
console.log('Event:', event.type, event.data);
res.sendStatus(200);
});
app.listen(3000);
F. Full DCR + PKCE walkthrough (CLI)
import crypto from 'crypto';
import open from 'open';
import http from 'http';
import fetch from 'node-fetch';
const ISSUER = 'https://mcp.shuuka.com';
// 1. Discover
const meta = await (await fetch(`${ISSUER}/.well-known/oauth-authorization-server`)).json();
// 2. DCR
const reg = await (await fetch(meta.registration_endpoint, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
client_name: 'Demo MCP CLI',
redirect_uris: ['http://localhost:53682/callback'],
grant_types: ['authorization_code', 'refresh_token'],
response_types: ['code'],
token_endpoint_auth_method: 'none',
scope: 'identity:read links:read analytics:read',
}),
})).json();
// 3. PKCE
const verifier = crypto.randomBytes(32).toString('base64url');
const challenge = crypto.createHash('sha256').update(verifier).digest('base64url');
const state = crypto.randomBytes(16).toString('base64url');
// 4. Local callback server
const codePromise = new Promise(resolve => {
http.createServer((req, res) => {
const url = new URL(req.url, 'http://localhost:53682');
if (url.pathname !== '/callback') return res.end('not found');
if (url.searchParams.get('state') !== state) return res.end('state mismatch');
res.end('You can close this window.');
resolve(url.searchParams.get('code'));
}).listen(53682);
});
// 5. Open authorize URL
const authUrl = new URL(meta.authorization_endpoint);
authUrl.searchParams.set('response_type', 'code');
authUrl.searchParams.set('client_id', reg.client_id);
authUrl.searchParams.set('redirect_uri', 'http://localhost:53682/callback');
authUrl.searchParams.set('scope', 'identity:read links:read analytics:read');
authUrl.searchParams.set('state', state);
authUrl.searchParams.set('code_challenge', challenge);
authUrl.searchParams.set('code_challenge_method', 'S256');
await open(authUrl.toString());
const code = await codePromise;
// 6. Exchange
const tokens = await (await fetch(meta.token_endpoint, {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({
grant_type: 'authorization_code',
code,
redirect_uri: 'http://localhost:53682/callback',
client_id: reg.client_id,
code_verifier: verifier,
}),
})).json();
console.log('Access token:', tokens.access_token);
More
- See Tool Reference for the full catalog.
- See Authentication for scope semantics.
- See Webhooks for delivery details.
- Open an issue at github.com/shuuka/mcp-feedback for problems or feature requests.