---
name: porter-guild-integrations
description: Turn a public API or MCP server into a private Guild integration draft with Porter. Use when the user wants to add, import, or connect an API, MCP server, or GraphQL endpoint to Guild (guild.ai), or asks whether Guild can take an API.
---

# Porter: carry an API into Guild

Porter (https://porter-guild.dev) searches integrations.sh, checks what Guild's importer accepts, and gives you one command that builds a **private, unpublished** Guild integration draft on this machine with the user's `guild` CLI. It supports OpenAPI, GraphQL, and MCP surfaces with API-key, no-auth, and OAuth 2.0 sign-in.

## Rules

- Never publish. Leave `guild integration version publish` for the user.
- Never connect a provider credential, and never ask for an API key or OAuth client secret in chat or put one on a command line.
- Never read, print, or send the Guild token. Porter never needs it.
- Read https://porter-guild.dev/v1/apply.ts before running it the first time.

## Workflow

1. **Check the machine.** `guild auth status` must say authenticated; if not, ask the user to run `guild auth login`. Node 18+ must be installed.
2. **Find the API.** MCP tool `search_apis`, or `GET https://porter-guild.dev/v1/search?q=<name>`. Each result has a `domain`, `surfaceSlug`, and `kind` (openapi, graphql, mcp).
3. **Check it.** MCP tool `resolve_api`, or `GET https://porter-guild.dev/v1/resolve?domain=<domain>&surface=<surfaceSlug>&kind=<kind>`. If `supported` is false, tell the user the `reason` and stop. If it is true, note `authScheme` (api-key, none, or oauth) and, for OAuth, the `oauth` block: install and token URL, scopes, and whether the provider registers clients itself (`registrationEndpoint`).
4. **Build the draft.** Run in a terminal:
   ```
   npx -y https://porter-guild.dev/porter.tgz <domain> <surfaceSlug> [--kind=mcp|graphql]
   ```
   Add `--dry-run` to print the `guild` commands without creating anything. The MCP tool `get_apply_command` returns the exact command and a ready-made prompt.
5. **Read the outcome.** Every run ends with one line `porter-result: {...}`:
   - `built`: the draft exists. Report the integration name, what was imported, and the publish command it printed.
   - `needs-oauth-app` (exit 2): the provider has no self-registration. Tell the user where to create an OAuth app, the redirect URL (`https://app.guild.ai/api/credentials/callback`), and the scopes. When they give you the client ID, run the same command with `--client-id=<id>`. For the secret, ask them to set `PORTER_OAUTH_CLIENT_SECRET` or save it to a file for `--client-secret-file=<path>`.
   - `needs-connection` (exit 2): an OAuth MCP server needs the user to sign in from the Guild dashboard (Access & setup > Credentials > Connect, or the integration's Versions > draft > Test > Connect) before Guild can read its tools. Wait until they say they are connected, then run the same command again. Porter reuses the integration.
   - `failed` (exit 1): report `message`. A key-based MCP server that needs a key first prints the `guild integration connect` command for the user.

## Script flags

| Flag | Use |
| - | - |
| `--kind=openapi\|graphql\|mcp` | Surface kind; openapi is the default |
| `--name=<integration>` | Integration name, if the default is taken |
| `--dry-run` | Print commands only |
| `--auth=oauth\|api-key` | Choose when both are offered; a key wins by default |
| `--client-id=<id>` | OAuth app client ID |
| `--client-secret-file=<path>` | OAuth client secret from a file (or `PORTER_OAUTH_CLIENT_SECRET`) |
| `--public-client` | OAuth app with no secret |
| `--no-register` | Skip automatic client registration |
| `--scopes=a,b` | Override OAuth scopes |
| `--token-auth=basic\|body` | How the token endpoint takes client credentials |
| `--pkce=on\|off` | Override PKCE |
| `--auth-param=key=value` | Extra authorize URL parameter, repeatable |
| `--install-url=<url>` `--token-url=<url>` | OAuth URLs from the provider's docs when Porter cannot find them |

## Porter endpoints

- MCP (streamable HTTP): `https://mcp.porter-guild.dev/mcp`. Tools: `search_apis`, `resolve_api`, `list_operations`, `get_apply_command`, `get_porter_skill`, plus catalog tools.
- `GET https://porter-guild.dev/v1/search?q=` search integrations.sh
- `GET https://porter-guild.dev/v1/resolve?domain=&surface=&kind=[&auth=oauth]` recipe or rejection reason
- `GET https://porter-guild.dev/v1/openapi?domain=&surface=&kind=` the normalized OpenAPI document Guild imports
- `GET https://porter-guild.dev/v1/prompt?domain=&surface=&kind=` a plain-text agent prompt
- `GET https://porter-guild.dev/v1/apply.ts` the script `porter.tgz` runs

Guild's own docs: https://docs.guild.ai/integrations/overview and https://docs.guild.ai/services/create-an-integration
