Go Back to Parent Doc

Developer Reference

Sokket is built to be extended through exactly one seam: a filter that registers tools. Everything else — transport, auth, permissions, audit — is written once and applies to your tools identically.

Text domain: sokket-site-connector-for-mcp · Prefix: sokket_ / SOKKET_ · Namespace: SOKKET\ (PSR-4 → includes/).

Registering a tool

add_filter( 'sokket_register_tools', function ( array $tools ) {
    $tools[] = array(
        'name'         => 'get_order_summary',
        'description'  => 'Get a summary of a WooCommerce order by id.',
        'capability'   => 'edit_shop_orders',
        'is_write'     => false,
        'group'        => 'other',
        'input_schema' => array(
            'type'       => 'object',
            'required'   => array( 'order_id' ),
            'properties' => array(
                'order_id' => array(
                    'type'        => 'integer',
                    'description' => 'The order id.',
                ),
            ),
        ),
        'callback'     => function ( array $args ) {
            $order = wc_get_order( absint( $args['order_id'] ) );

            if ( ! $order ) {
                return new WP_Error( 'not_found', 'No such order.' );
            }

            return array(
                'id'     => $order->get_id(),
                'status' => $order->get_status(),
                'total'  => $order->get_total(),
            );
        },
    );

    return $tools;
} );

Your tool immediately appears in the token allowlist on Settings → Access, in tools/list for connections that may call it, and in the audit log.

Tool definition schema

KeyTypeRequiredMeaning
namestring✔Unique key matching ^[a-z0-9_]{1,64}$.
descriptionstring✔Shown to the AI client — this is the model’s only instruction on when to use the tool, so write it for a reader who can’t see your code.
capabilitystring✔Checked with current_user_can() before the callback runs.
is_writebool✔Must be a real boolean. true means the read-only ceiling blocks it.
is_destructivebool—true when the tool removes content. Implies is_write, sends the MCP destructiveHint annotation, and shows a delete badge in the token allowlist. Defaults to false.
callbackcallable✔function ( array $args ): array|WP_Error.
input_schemaarray—JSON Schema for the arguments object. Omit for a tool with no arguments.
groupstring—Admin grouping key. Defaults to other.

Invalid definitions are silently discarded, and the first registration of a name wins — so a filter cannot overwrite a built-in tool by re-registering its name.

Groups

Built-in group keys and labels: site (Site & diagnostics), content (Content), media (Media), taxonomy (Taxonomies & terms), comments (Comments), and other (Other). A tool declaring an unknown group falls into the trailing Other bucket in the admin.

Writing a good callback

  • Return an array on success — it is JSON-encoded into the tool result. Return a WP_Error on failure and Sokket turns it into a proper JSON-RPC error.
  • Re-check per-object permissions inside the callback. The definition’s capability is only the outer gate. If your tool acts on a specific object, call current_user_can( 'edit_post', $id ) (or the equivalent) yourself — the built-in post, term, and comment tools all do.
  • Sanitize every argument. Arguments come from a remote client. Never pass one into a query, a path, or an option name unfiltered.
  • Set is_write honestly. It is what the read-only ceiling keys off. A tool that changes anything and declares false silently defeats a security control the site owner is relying on.
  • Don’t make outbound requests. The free plugin’s "no outbound calls" guarantee is per-codebase; if your add-on calls out, say so in your own documentation rather than quietly borrowing Sokket’s claim.
  • Throw nothing. Uncaught Throwables are caught and converted into a generic internal error, so exceptions cost you your error message.

Every hook

Tools

  • sokket_register_tools (filter) — the tool definition array. The only extension seam.
  • sokket_settings_read_allowlist (filter) — the options get_site_settings may read, as group => array( option names ). Anything you add here is exposed to every connection allowed to call that tool.

Uploads

  • sokket_allowed_upload_mimes (filter) — allowed upload MIME types. Defaults to JPEG, PNG, GIF, WebP, and AVIF. SVG is refused by the type-sniffing layer regardless of what you return here.
  • sokket_max_upload_size (filter) — maximum bytes per file. Default 8 MB.
  • sokket_max_uploads_per_hour (filter) — file count cap per user per hour. Default 20.
  • sokket_max_upload_bytes_per_hour (filter) — byte cap per user per hour. Default 25 MB.

Auth & OAuth

  • sokket_rate_limit_per_minute (filter) — requests per minute per credential. Default 120; return 0 or less to disable.
  • sokket_oauth_user_can_authorize (filter) — whether the current user may approve an OAuth connection. Defaults to current_user_can( 'read' ).
// Only editors and above may approve MCP connections.
add_filter( 'sokket_oauth_user_can_authorize', function () {
    return current_user_can( 'edit_others_posts' );
} );

Audit

  • sokket_audit_max_rows (filter) — audit log row cap. Default 500, minimum 10.

Admin

  • sokket_screen_ids (filter) — the plugin’s admin screen ids.
  • sokket_admin_header_nav (filter) — the header nav items.
  • sokket_before_sidebar_content / sokket_after_sidebar_content (actions) — render into the admin sidebar.
  • sokket_admin_page_after_content (action) — render after the main admin content.

The transport contract

One REST route: POST /wp-json/sokket/v1/mcp, Streamable HTTP carrying JSON-RPC 2.0.

Methods: initialize, ping, tools/list, tools/call, and the notifications/initialized no-op. Anything else returns method-not-found.

Protocol versions: 2025-11-25, 2025-06-18, 2025-03-26. initialize echoes a supported requested version, or replies with the newest one when the request names something else.

Capabilities: the handshake advertises tools with listChanged: false. The server never pushes a tool-list-changed notification, so clients refresh their tool list by re-initializing.

Sessions: a successful initialize returns an Mcp-Session-Id header, backed by a transient with a 15-minute sliding expiry. Send it back on later requests. An unknown or expired id gets 404 so the client re-initializes. DELETE with the header ends the session.

Other verbs: GET returns 405 with Allow: POST, DELETE — there is no server-initiated stream.

Batching: JSON-RPC batching is accepted only for a session negotiated at 2025-03-26, the last protocol version that allowed it, and is size-capped. Newer sessions get an invalid-request error.

Auth precedence: an Authorization: Bearer header prefixed sokket_at_ is treated as an OAuth access token; one prefixed sokket_ is a manual token. Any other Bearer value is left alone for other plugins’ auth handlers. With no bearer header, Sokket falls back to whatever user WordPress already authenticated — the Application Password path.

Permission callback order: master toggle → origin validation → authentication. A disabled server rejects before anything is parsed.

OAuth endpoints

PurposeRoute
Discovery (RFC 9728)/.well-known/oauth-protected-resource
Discovery (RFC 8414)/.well-known/oauth-authorization-server
Authorization/sokket-oauth/authorize
Token/wp-json/sokket/v1/oauth/token
Registration/wp-json/sokket/v1/oauth/register
Revocation/wp-json/sokket/v1/oauth/revoke

Grants: authorization_code and refresh_token. PKCE S256 required. Scopes: mcp:read, mcp:write. Lifetimes: code 5 minutes, access token 1 hour, refresh token 30 days. The two discovery documents are matched on init rather than registered as REST routes, because they must live at the host root above the REST namespace.

Note that OAuth contexts carry no per-tool allowlist — a grant may call every tool its user has the capability for, bounded by its read-only scope. Per-tool control is a bearer-token feature.

Database schema

TableHolds
{prefix}sokket_tokensBearer tokens (SHA-256), bound user, allowlist JSON, read-only flag, active flag, timestamps.
{prefix}sokket_audit_logCapped tool-call log: token id, user id, tool name, outcome, object id, timestamp.
{prefix}sokket_oauth_clientsRegistered clients, redirect URIs, hashed secrets.
{prefix}sokket_oauth_codesShort-lived authorization codes.
{prefix}sokket_oauth_tokensHashed access and refresh tokens with their scope.

Options: sokket_settings, sokket_version. Transients are prefixed sokket_. A scheduled sokket_oauth_cleanup task prunes expired codes and tokens. uninstall.php removes all of it.

Building an add-on

The Pro plugin uses nothing but sokket_register_tools — no forks, no patches, no private APIs. If you’re building filesystem, database, or deployment tooling on top of Sokket, that filter is the whole integration surface, and everything you register inherits the permission model, the audit log, and the transport for free.

Related

Shopping Cart
  • Your cart is empty.