MCP server
Connect Codex, ChatGPT, Claude, Cursor, or Inspector through OAuth-protected tools.
- Documentation owner:
- BlendDuck Documentation
- Last reviewed:
BlendDuck exposes a remote Streamable HTTP MCP server:
https://blendduck.com/api/mcp
The server uses Better Auth for OAuth discovery, dynamic client registration, PKCE, consent, refresh tokens, and JWT validation. MCP clients never receive a BlendDuck session cookie or social-provider credential.
BlendDuck MCP currently accepts OAuth JWTs, not organization API keys. Leave a
client's Bearer token environment variable and header fields empty.
Organization API keys remain the headless REST/SDK/Zapier/n8n credential for
/api/v1; they are not accepted by /api/mcp.
Connect Codex
Authenticate to BlendDuck with email OTP first. Guest sessions cannot approve
an MCP grant. For a local quickstart, replace https://blendduck.com below
with the exact APP_URL, such as http://localhost:5001.
In the Codex app:
- Open Settings → Plugins → MCP → Add server.
- Choose Streamable HTTP and enter
https://blendduck.com/api/mcp. - Leave Bearer token environment variable, static headers, and environment headers empty. Save and restart Codex.
- Select Authenticate, sign in to BlendDuck, choose the organization on the consent screen, and select Allow access.
- Type
/mcp, then ask Codex to list the connected channels without making changes.
The Codex app, CLI, and IDE extension share the same local MCP configuration. The equivalent CLI setup is:
codex mcp add blendduck \
--url https://blendduck.com/api/mcp \
--oauth-resource https://blendduck.com/api/mcp
codex mcp login blendduck
The default grant is read-only. Request write scope only when the client needs to create, schedule, or publish posts:
codex mcp login blendduck \
--scopes openid,profile,email,offline_access,blendduck:read,blendduck:write
Connect other clients
All supported clients use the same endpoint and OAuth contract. Copy the
checked examples from
examples/mcp,
or use the native commands below:
claude mcp add --transport http blendduck https://blendduck.com/api/mcp
pnpm dlx @modelcontextprotocol/inspector@2.0.0 https://blendduck.com/api/mcp
Cursor reads the same URL from .cursor/mcp.json. Run cursor agent login
once to select the Cursor identity, then authorize BlendDuck when the MCP server
is first used. ChatGPT web does not read local Codex configuration. An eligible
Developer mode workspace can create a custom app for the public HTTPS endpoint.
A validated BlendDuck plugin package bundles the production endpoint, OAuth
base read/write scopes, write-tool approval prompts, logo, and
organization-bound workflow guidance for optional public distribution.
Complete OAuth in the client, then use list_channels before making a
draft-only create_post check. No API key or social-provider credential is
entered during setup.
The deployed Registry manifest is versioned with the runtime.
BlendDuck 3.2.0 is published and active under the domain-owned name
com.blendduck/blendduck in the
official MCP Registry.
Tools
| Tool | Scope | Purpose |
|---|---|---|
list_channels | blendduck:read | List connected channels and publishing support |
get_provider_contract | blendduck:read | Read one provider's Zod-derived full post/settings schemas and media constraints |
get_channel_health | blendduck:read | Inspect safe connection state and the next queue slot |
validate_post | blendduck:read | Validate content, media, thread, and settings without writing |
list_posts | blendduck:read | List posts with date, channel, state, and campaign filters |
get_post | blendduck:read | Read one post and its delivery state |
create_post | blendduck:write | Idempotently draft, queue, schedule, prioritize, or publish a post |
update_post | blendduck:write | Idempotently update content, media, campaigns, or lifecycle mode |
duplicate_post | blendduck:write | Create a fresh draft copy and all channel variants |
cancel_post | blendduck:write | Cancel one target before it reaches a provider |
retry_post | blendduck:write | Retry one eligible failed provider target |
delete_post | blendduck:write | Permanently delete a mutable post or target |
list_campaigns | blendduck:read | List canonical campaign tags and usage counts |
reschedule_post | blendduck:write | Move one mutable target to an explicit date-time |
bulk_calendar_action | blendduck:write | Run a bounded best-effort calendar command |
list_media | blendduck:read | List reusable tenant media and authoritative metadata |
import_media | blendduck:write | Import a public media URL into tenant-owned storage |
get_analytics | blendduck:read | Compare normalized metrics with filters, freshness, and content attribution |
get_inbox | blendduck:read | Read a filtered Social Inbox queue and sync health without sending or moderating |
list_approvals | blendduck:read | List visible approval cycles and allowed actions |
manage_approval | blendduck:write | Submit or decide an approval with server-side authorization |
OAuth consent binds the connection to exactly one organization. Tools infer that organization from the access token, never expose tenant selection, and recheck membership on every call. Tool metadata distinguishes read-only, external-write, destructive, and non-idempotent operations so MCP clients can ask for the right approval.
Post, recovery, rescheduling, and bulk commands require a stable requestId.
duplicate_post, import_media, and manage_approval are explicitly
non-idempotent and should not be automatically repeated after an ambiguous
response. allowDuplicate: true is reserved for an intentional repeat inside
the configured content-deduplication window.
Optional OpenAPI categories
The 21 task-oriented tools remain the default. Resource-oriented agents may authorize only the stable v1 categories they need:
| Category | OAuth scope | Derived tools |
|---|---|---|
| Channels | blendduck:tools:channels | 3 |
| Posts | blendduck:tools:posts | 5 |
| Media | blendduck:tools:media | 2 derived + 3 secure upload |
| Providers | blendduck:tools:providers | 2 |
| Webhooks | blendduck:tools:webhooks | 8 |
This example adds only the two provider resource tools:
codex mcp login blendduck \
--scopes openid,profile,email,offline_access,blendduck:read,blendduck:tools:providers
Generated tools use names such as api_list_providers and
api_update_post. Their input and structured { data, meta } output schemas
come from the reviewed OpenAPI contract; their execution still calls the same
audited application services as REST and the dashboard. Category scope does
not replace blendduck:read or blendduck:write. Public REST derives the
organization from its API key; OAuth MCP derives the same boundary from the
organization selected during consent.
Credential management, session-only setup, one-time webhook secrets, and multipart file bytes are excluded. Local media upload uses a separate secure browser session so an agent never needs to embed file bytes or receive storage credentials.
Upload a local file for an agent
Local-file hand-off is opt-in and needs the Media category plus both base scopes:
codex mcp login blendduck \
--scopes openid,profile,email,offline_access,blendduck:read,blendduck:write,blendduck:tools:media
- Call
create_media_upload_sessionand show itsbrowserUrlto the person. Keep the returnedsession.idfor polling. - The same signed-in user opens the 15-minute link and chooses one image or video. BlendDuck uploads, reads back, and inspects the bytes in the original workspace.
- Call
get_media_upload_sessionuntil state iscompleted. - Call
attach_uploaded_mediawith that session ID, the logicalpostId, and a stablerequestId.
The database stores only a digest of the browser capability, which expires after 15 minutes even when the upload has completed. The separate non-secret session ID remains available for agent polling. Another member, another workspace, an expired link, or a foreign media URL cannot complete the session. Attachment uses the normal media preflight, content-approval edit rules, audit trail, atomic session claim, and idempotent multi-target post update; a session cannot be redirected to a second post.
Checked first calls
After consent, call list_channels; the selected organization is already
bound to the connection. To verify write access without an external publish,
call create_post with one returned channel, mode: "draft", and a stable
requestId. The response shape is:
{
"mode": "draft",
"posts": [
{
"postId": "<target-id>",
"aggregateId": "<post-id>",
"integration": "<channel-id>"
}
]
}
The repository quickstart verifier performs discovery, dynamic client registration, S256 PKCE, signed consent, token exchange, unauthenticated challenge, MCP initialization, tool listing, organization-bound channel reads, an idempotently replayed draft write, and a real local PNG browser hand-off through all three secure Media tools against a fresh local server.