API Reference Last updated March 14, 2026

Execute Tool

The core AgentBridge endpoint. Send a provider slug, tool name, and parameters — AgentBridge retrieves the user's encrypted OAuth token, calls the upstream provider API, and returns a normalized response with latency tracking and execution logging.

Endpoint #

POST /api/mcp/execute
http — request headers
Authorization: Bearer ab_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Content-Type: application/json

Requires a write or admin scoped API key. A read-scoped key will receive a 403 Forbidden response.

Request Body #

All fields must be JSON. The params object schema is specific to each provider and tool — consult the Integrations docs for per-provider tool schemas.

provider required string The slug of the MCP provider. Must match an active integration for the API key's user. Valid values: "notion", "slack", "github", "google-drive", "gmail".
tool required string The tool name to execute within the provider. Must be a valid tool for the specified provider. Example: "create_page", "send_message", "create_issue".
params required object Key-value parameters for the tool. Schema varies by provider and tool. Extra keys are silently ignored; missing required keys return a 422 with the provider's validation error.
userId optional string Reserved for future multi-user workspace support. Currently ignored — the API key's owner is always used as the actor.

Shorthand Format #

Instead of specifying provider and tool separately, you can combine them into a single provider.tool string and omit the provider field entirely. This is especially useful when routing tool calls from an LLM — you can pass the string returned by GET /mcp/tools directly.

json — shorthand (provider.tool)
{
  "tool":   "github.create_issue",
  "params": {
    "repo":  "acme/backend",
    "title": "Fix memory leak in worker"
  }
}

Both forms are fully equivalent. Use whichever fits your workflow:

Explicit form { "provider": "github", "tool": "create_issue", "params": {...} }
Shorthand form { "tool": "github.create_issue", "params": {...} }

Use GET /mcp/tools to retrieve all available provider.tool strings in one request.

Response #

Successful executions return HTTP 200 with a consistent JSON envelope. The data field contains the normalized response from the upstream provider.

json — 200 success
{
  "status": "success",
  "data": { /* provider-specific response */ },
  "latencyMs": 312,
  "executionId": "exec_01hxyz..."
}
status "success" Always "success" on 200 responses.
data object Response data from the provider, normalized to a flat or nested JSON object. Shape varies by provider and tool.
latencyMs number End-to-end latency in milliseconds, including token decryption, any token refresh, and the upstream provider round-trip.
executionId string Unique identifier for this execution. Use this to look up the full execution log via GET /logs/:id.

Examples #

Notion — Create Page #

Create a new page inside a Notion database or parent page.

json — request
{
  "provider": "notion",
  "tool":     "create_page",
  "params": {
    "parent_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "title":     "Meeting Notes — March 14",
    "content":   "Agenda: Q1 review, roadmap planning, hiring update."
  }
}
json — 200 response
{
  "status": "success",
  "data": {
    "id":           "page_789xyz",
    "url":          "https://notion.so/Meeting-Notes-March-14-789xyz",
    "created_time": "2026-03-14T10:30:00.000Z"
  },
  "latencyMs":   312,
  "executionId": "exec_01hxyz7a9b..."
}

Slack — Send Message #

Post a message to a Slack channel using its channel ID.

json — request
{
  "provider": "slack",
  "tool":     "send_message",
  "params": {
    "channel": "C012AB3CD",
    "text":    "Deployment to production completed successfully."
  }
}
json — 200 response
{
  "status": "success",
  "data": {
    "ok":      true,
    "ts":      "1710432000.123456",
    "channel": "C012AB3CD"
  },
  "latencyMs":   198,
  "executionId": "exec_01hyza3b4c..."
}

GitHub — Create Issue #

Open a new issue in a GitHub repository with optional labels and body text.

json — request
{
  "provider": "github",
  "tool":     "create_issue",
  "params": {
    "repo":   "acme/backend",
    "title":  "Fix memory leak in worker process",
    "body":   "Worker process memory grows unbounded after 24h uptime. See #142.",
    "labels": ["bug", "performance"]
  }
}
json — 200 response
{
  "status": "success",
  "data": {
    "id":     2048319,
    "number": 157,
    "url":    "https://github.com/acme/backend/issues/157",
    "state":  "open"
  },
  "latencyMs":   421,
  "executionId": "exec_01hzab5d6e..."
}

Error Responses #

400 — Provider Not Connected #

The requested provider has no active integration for this user.

json — 400
{
  "statusCode": 400,
  "message":    "Integration not found for provider: notion",
  "error":      "Bad Request"
}

422 — Provider Returned Error #

AgentBridge successfully called the upstream API but the provider responded with an error.

json — 422
{
  "statusCode":    422,
  "message":       "Provider returned an error",
  "error":         "Unprocessable Entity",
  "providerError": {
    "object":  "error",
    "status":  403,
    "code":    "restricted_resource",
    "message": "Insufficient permissions to access this resource."
  }
}

The providerError field contains the raw error body from the upstream provider. Its shape varies by provider. Always check statusCode === 422 and inspect providerError for provider-specific error codes and messages.

404 — Tool Not Found #

The tool name does not exist for the given provider.

json — 404
{
  "statusCode": 404,
  "message":    "Tool 'create_pge' not found for provider: notion",
  "error":      "Not Found"
}

Check the Integrations docs for the exact list of tool names per provider. Tool names are case-sensitive and use snake_case.

Retries #

AgentBridge does not retry failed requests automatically. Implement client-side retry logic for transient errors:

  • 429 (rate limited): Wait until the Unix timestamp in the X-RateLimit-Reset header, then retry once.
  • 500 (server error): Retry with exponential backoff: 1s, 2s, 4s, then give up after 3 attempts.
  • 502 (bad gateway): The upstream provider was unreachable. Retry after 5-10 seconds.

Do not retry the following status codes — they indicate a client or data problem that will not resolve on retry:

  • 400 — Fix the request (connect the integration or correct the body)
  • 401 — Fix the API key
  • 403 — Use a key with the correct scope
  • 404 — Fix the tool name
  • 422 — Fix the tool parameters or resolve the provider-side issue

Idempotency #

POST /api/mcp/execute is not idempotent. Each call creates a new execution log entry and may create side effects in the target system. For example:

  • Calling create_page twice creates two separate Notion pages
  • Calling send_message twice sends two Slack messages
  • Calling create_issue twice opens two GitHub issues

AgentBridge does not currently support idempotency keys. To avoid duplicate side effects, implement idempotency checks in your agent logic. You can use GET /logs to verify whether a previous execution succeeded before retrying.

typescript — idempotency check example
import { AgentBridge } from 'agentbridge-sdk';

const bridge = new AgentBridge(process.env.AGENTBRIDGE_API_KEY!);

// Check recent logs before retrying a create operation
const logs = await bridge.logs.list({ page: 1, limit: 5 });
const alreadyCreated = logs.data.some(
  log => log.provider === 'notion'
    && log.tool === 'create_page'
    && log.status === 'success'
);

if (!alreadyCreated) {
  await bridge.execute({
    provider: 'notion',
    tool: 'create_page',
    params: { parent_id: 'abc', title: 'Report' },
  });
}