Discover tools on demand instead of loading hundreds into context.
- Discover —
capabilities_discover with a task description
- Install —
capability_details with tool names (map to your model’s function-calling format)
- Invoke —
tools/call on the server path
Both discovery tools live on /pinkfish-sidekick. For full parameter schemas, see the Pinkfish Workflow Building server reference.
End-to-End Example
const MCP_URL = "https://mcp.app.pinkfish.ai";
const TOKEN = "<YOUR_PLATFORM_JWT>";
const headers = {
Authorization: `Bearer ${TOKEN}`,
"Content-Type": "application/json",
Accept: "application/json",
};
async function callTool(serverPath, toolName, args) {
const resp = await fetch(`${MCP_URL}${serverPath}`, {
method: "POST",
headers,
body: JSON.stringify({
jsonrpc: "2.0",
method: "tools/call",
params: { name: toolName, arguments: args },
id: 1,
}),
});
const result = await resp.json();
if (result.error) throw new Error(result.error.message);
return result.result;
}
function parseResult(r) {
if (r?.structuredContent) return r.structuredContent;
return JSON.parse(r?.content?.[0]?.text ?? "{}");
}
async function discover(task) {
const r = await callTool("/pinkfish-sidekick", "capabilities_discover", { request: task });
return parseResult(r);
}
async function getDetails(items) {
const r = await callTool("/pinkfish-sidekick", "capability_details", { items });
return parseResult(r);
}
// 1. Discover
const capabilities = await discover("search the web for AI news");
const topTool = capabilities.tools?.[0];
if (!topTool) throw new Error("No tools found");
// 2. Install (optional — get schema when you need parameter details)
const details = await getDetails([topTool.name]);
// 3. Invoke
const result = await callTool(`/${topTool.serverName}`, topTool.name, {
q: "latest AI news 2026",
});
console.log(parseResult(result));
Node.js 18+ or browser. Python: requests.post() with same JSON-RPC payload.
capabilities_discover
Describe the task; get matching tools and connections.
curl -s -X POST "https://mcp.app.pinkfish.ai/pinkfish-sidekick" \
-H "Authorization: Bearer $PINKFISH_TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"name": "capabilities_discover",
"arguments": {
"request": "search my gmail for unread emails"
}
},
"id": 1
}'
Parameters:
| Parameter | Required | Description |
|---|
request | Yes | Natural language description of the task |
types | No | Filter results: ["tool"], ["connection"], ["resource"], ["agentSkill"], or combinations |
context | No | "workflow-creation" or "agent-execution" — filters available skills |
Response:
{
"tools": [
{
"name": "gmail_search_emails",
"serverName": "gmail",
"hasSkill": false,
"confidence": 0.95
}
],
"connections": [
{
"name": "My Gmail",
"id": "abc123-pcid",
"application": "gmail",
"confidence": 0.95
}
],
"resources": [],
"skills": []
}
| Field | Use |
|---|
tools[].name | Tool name for tools/call |
tools[].serverName | Server path (e.g. gmail → /gmail) |
connections[].id | PCID for application tools |
capability_details
Pass tool names; get full parameter schemas.
curl -s -X POST "https://mcp.app.pinkfish.ai/pinkfish-sidekick" \
-H "Authorization: Bearer $PINKFISH_TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"name": "capability_details",
"arguments": {
"items": ["gmail_search_emails"]
}
},
"id": 1
}'
Parameters:
| Parameter | Required | Description |
|---|
items | Yes | Tool names from discovery (use tools[].name, not serverName) |
types | No | Filter: ["tool"], ["connection"], ["resource"], ["agentSkill"] |
Key Points
- Embedded tools: no PCID required. Application tools: use PCID from discovery or see Connecting to MCPs.
- Pass
tool.name to capability_details, not serverName.
- Install only what the user needs (typically 1–5 tools per task).
Custom Agents
Bootstrap with these two discovery tools. On user task: discover → fetch schemas → map to your model’s function-calling format → add to agent context. Route model tool calls through tools/call.
The example above invokes a discovered tool by calling tools/call directly on its server path
(/${serverName}). That works when your agent can issue arbitrary HTTP calls at runtime. Many agents can’t:
no-code and low-code agent platforms have a fixed set of pre-registered tools and no way to add an endpoint
per discovered tool.
For these, register three fixed tools and route every discovered tool through gateway_invoke on
/gateway, which dispatches internally by server + tool:
curl -s -X POST "https://mcp.app.pinkfish.ai/gateway" \
-H "Authorization: Bearer $PINKFISH_TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"name": "gateway_invoke",
"arguments": {
"server": "gmail",
"tool": "gmail_send_email",
"arguments": { "PCID": "abc123-pcid", "to": "jane@acme.com", "subject": "Hi", "body": "…" }
}
},
"id": 1
}'
So the three tools you give the agent are: capabilities_discover and capability_details (both on
/pinkfish-sidekick), and gateway_invoke (on /gateway). The agent never calls a discovered tool directly —
it passes the discovered serverName/name into gateway_invoke. See
Gateway for the full meta-tool set and the
Bring Your Own Agent prompt variant.
If your platform’s tools are strongly typed and can’t express a nested arguments object, pass
gateway_invoke’s arguments as a JSON string and have the tool inject it into the request body so it
renders as real JSON.
Two invocation modes at a glance
| Your agent can… | Invoke a discovered tool by… |
|---|
| Make arbitrary HTTP calls / add tools at runtime | tools/call on /${serverName} with the tool name (shown above) |
| Only use a fixed, pre-registered tool set (no-code platforms) | gateway_invoke on /gateway, passing server + tool + arguments |
Code Execution Shortcut
Code Execution chains tools without installing them. Discover tools, then pass tool calls into a single code-execution_execute invocation.