Tools API
GET /api/v1/tools and POST /api/v1/tools/execute — list tool definitions and execute tools with auth injection.
List Tools
GET /api/v1/toolsReturns all enabled tools from approved plugins with their JSON Schema definitions. Tools from plugins that are still in draft, pending_review, declined, or revision_requested status are excluded.
Authentication
API key required: Authorization: Bearer nk_live_...
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
plugin | string | No | Comma-separated plugin slugs to filter by |
userId | string | No | End-user ID for realtime MCP tool discovery. When provided and the plugin has MCP configured, NIN fetches tools live from the MCP server using the user's access token. Falls back to cached tools on failure. |
Example (manual): GET /api/v1/tools?plugin=gmail,stripe
Example (MCP with realtime): GET /api/v1/tools?plugin=notion&userId=user_123
Response
Each tool includes a source field indicating whether it was defined manually or discovered from an MCP server:
{
"tools": [
{
"id": "550e8400-e29b-41d4-a716-446655440001",
"slug": "GMAIL_SEND_EMAIL",
"name": "Send Email",
"description": "Send an email via Gmail API",
"method": "POST",
"path": "/gmail/v1/users/me/messages/send",
"inputSchema": {
"type": "object",
"properties": {
"to": { "type": "string" },
"subject": { "type": "string" },
"body": { "type": "string" }
},
"required": ["to", "subject", "body"]
},
"outputSchema": null,
"pluginSlug": "gmail",
"pluginName": "Gmail",
"source": "manual"
},
{
"id": "mcp-notion-search",
"slug": "NOTION_SEARCH",
"name": "notion-search",
"description": "Search across a Notion workspace",
"inputSchema": {
"type": "object",
"properties": {
"query": { "type": "string" }
},
"required": ["query"]
},
"pluginSlug": "notion",
"pluginName": "Notion",
"source": "mcp"
}
]
}Execute Tool
POST /api/v1/tools/executeExecute a tool for a specific end-user. The runtime proxy resolves the tool, decrypts the user's credentials, injects auth headers, calls the external API, and returns the result.
Authentication
API key required: Authorization: Bearer nk_live_...
Request Body
{
"userId": "user_123",
"tool": "GMAIL_SEND_EMAIL",
"params": {
"to": "hello@example.com",
"subject": "Hello",
"body": "Sent by an AI agent"
}
}| Field | Type | Required | Description |
|---|---|---|---|
userId | string | Yes | Your app's end-user identifier |
tool | string | Yes | Tool slug (e.g. GMAIL_SEND_EMAIL) |
params | object | No | Parameters matching the tool's input schema |
Response (Success — 200)
{
"success": true,
"data": { "messageId": "abc123" },
"status": 200,
"latencyMs": 342
}Response (Error — 502)
{
"success": false,
"error": "Upstream API returned 403 Forbidden",
"status": 502,
"latencyMs": 1205
}Response Fields
| Field | Type | Description |
|---|---|---|
success | boolean | Whether the external API returned a success status |
data | any | The parsed response from the external API |
error | string | Error message (only when success is false) |
status | number | HTTP status code from the external API |
latencyMs | number | Round-trip execution time in milliseconds |
Execution Details
The proxy performs these steps:
For manual tools:
- Resolves the tool by
slug(only from approved plugins) - Fetches the plugin's
baseUrl - Finds the user's connected account for this plugin
- Decrypts credentials (AES-256-GCM)
- Injects auth headers based on auth method type
- Interpolates
{placeholder}path params fromparams - Sends remaining params as JSON body (for non-GET)
- Returns the response and logs the execution
For MCP tools:
- Resolves the tool by
slugfrommcpToolCache(only from approved plugins) - Finds the user's MCP connection for the plugin
- Decrypts the MCP access token (auto-refreshes if expired)
- Connects to the MCP server using the Streamable HTTP transport
- Calls the tool via the MCP protocol (
tools/call) - Returns the result and logs the execution
MCP Tool Discovery Behavior
When userId is provided and the plugin has MCP configured:
| Scenario | Behavior |
|---|---|
| User has MCP connection | Live fetch from MCP server, updates cache, returns fresh tools |
| User has no MCP connection | Falls back to mcpToolCache (previously synced tools) |
| Live fetch fails | Falls back to mcpToolCache |
| No cached tools either | Returns empty MCP tools for that plugin |