Skip to documentation
DocumentationService recipes

Recipes

A recipe tells Sallyport how to reach one service: its hosts, the key it takes, and how each call is classed.

On this page

What a recipe decides

The catalog holds one recipe per service: GitHub, Stripe, Cloudflare, AWS and more than a hundred others. A recipe says where the key goes, which hosts it may reach, and whether a call reads, writes or destroys.

A connection uses the recipe it was created from. Otherwise Sallyport picks the recipe whose host matches, and the most exact host wins. A host no recipe claims still works, classed by its method.

Read the catalog

GET /v1/recipes lists the catalog, filtered by q (name, key or vendor), vendor or host. GET /v1/recipes/{key} returns one. Both take a console key, see REST API.

JSON · GET /v1/recipes/github
{
  "data": {
    "key": "github",
    "name": "GitHub API",
    "vendor": "GitHub",
    "hosts": ["api.github.com"],
    "connection_hosts": ["api.github.com"],
    "connection_domains": [],
    "channel": "http",
    "adapter": "bearer",
    "adapters": ["bearer", "oauth2-ac"],
    "credential_fields": [
      { "name": "value", "label": "Personal access token or installation token", "secret": true, "required": true, "sent_as": [] }
    ],
    "methods": [
      {
        "adapter": "bearer",
        "fields": [
          { "name": "value", "label": "Personal access token or installation token", "secret": true, "required": true, "sent_as": [] }
        ],
        "provider": "",
        "sallyport_app": false,
        "redirect_uri": ""
      },
      {
        "adapter": "oauth2-ac",
        "fields": [],
        "provider": "GitHub",
        "sallyport_app": false,
        "redirect_uri": "https://mcp.sallyport.cloud/callback/upstream"
      }
    ],
    "notes": null,
    "docs_url": "https://docs.github.com/en/rest",
    "create_url": "https://github.com/settings/personal-access-tokens/new",
    "revoke_url": "https://github.com/settings/tokens",
    "scopes_recommended": [],
    "default_profile": "direct",
    "oauth": true,
    "version": 2
  },
  "request_id": "5d0c2f7e8a1b4c6d9e0f1a2b3c4d5e6f"
}
FieldMeaning
hostsHosts the service answers on. A leading *. covers every subdomain.
connection_hosts, connection_domainsHosts a new key connects to as they are, and domains under which you give your own address, such as acme.zendesk.com.
adapter, adaptersHow the key is presented: bearer, basic, header, api_key, aws-sigv4, oauth2-ac for signing in, and a few more.
credential_fieldsWhat a person types. secret says whether the value is a password. sent_as names the headers and query parameters a setting field is sent in on every call, and is empty for every other field.
methodsEvery way to connect the service, in the order the console offers them. A method with a provider is signing in at the vendor.
create_url, revoke_url, docs_urlWhere to issue the key, where to revoke it, and the vendor’s API reference.
default_profileThe rule a new agent and connection pair starts on. Every recipe says direct: read, write and destructive all run without asking.

The class rules and the key placement stay inside Sallyport and are not part of this answer.

How a call is classed

Every call is read, write or destructive. The agent’s rule for that class on the connection decides: run it, ask a person, or refuse.

  • The method sets the floor: GET, HEAD and OPTIONS read; POST, PUT and PATCH write; DELETE and any other method is destructive.
  • The recipe’s rules are tried in order and the first match wins. A rule only raises, and the only raise is a GET the vendor changes something with, which becomes a write. No recipe rule makes a call destructive.
  • A path segment that starts with webhook, hooks, build, trigger, send, invoke, execute, exec or run makes the call at least a write. A recipe rule that matches the path overrides this.
  • A recipe may list exact read operations that travel as POST, such as AWS DescribeInstances or a GraphQL query. They count as reads only when the whole request reads one way.
  • GraphQL, JSON-RPC and batch requests take the highest class of their parts.
  • Method overrides such as _method and X-HTTP-Method-Override are removed before the call is classed and sent.

Tools of an MCP server are classed by their own readOnlyHint and destructiveHint, and a tool that states neither is a write. SSH commands are writes, except a short list of exact reads, and commands such as rm or dd are destructive. See SSH commands. File operations on an SSH host are classed by what they do. list, stat and read are reads, write, mkdir and rename are writes. delete and rmdir are destructive, see Files over SFTP.

Checking a key

Some recipes, GitHub among them, name one harmless read that proves a key works: GET /user for GitHub. Sallyport runs it when a key is saved, when it is replaced, and when you press Check again.

A key the service refuses is marked on its page with the vendor’s own message. An answer that proves nothing, such as a missing permission, changes nothing.