Agent guide
Porter is built to be handed to an agent. Give it the skill, connect its MCP server, or copy the prompt on any API page. The agent finds the API, checks it, and builds a private Guild draft on your machine. Publishing stays with you.
Install the Porter skill
One file with the whole workflow: rules, steps, script flags, outcomes, and endpoints. Copy it into your agent once, and ask for things like “add Linear to Guild”.
| Agent | Where it goes |
|---|---|
| Claude Code | ~/.claude/skills/porter-guild-integrations/SKILL.md (or .claude/skills/ in a project) |
| Cursor | .cursor/rules/porter.mdc in your project |
| Codex CLI | AGENTS.md in your project, or ~/.codex/AGENTS.md |
| Gemini CLI | GEMINI.md in your project, or ~/.gemini/GEMINI.md |
| Any other agent | Paste it into the system prompt or project instructions |
Preview SKILL.md
---
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
Connect the MCP server
Porter's MCP server runs on the Porter API and lets an agent search and check APIs itself. It is read-only and needs no login: building the draft still runs on your machine through the command it returns.
https://mcp.porter-guild.dev/mcpClaude Code
claude mcp add --transport http porter https://mcp.porter-guild.dev/mcp
Cursor (~/.cursor/mcp.json)
{
"mcpServers": {
"porter": {
"url": "https://mcp.porter-guild.dev/mcp"
}
}
}Any other client that speaks streamable HTTP takes the same URL.
| Tool | What it does |
|---|---|
| search_apis | Search integrations.sh live for OpenAPI, GraphQL, and MCP surfaces. |
| resolve_api | Check whether Guild can take a surface, and how it signs in (key, none, or OAuth). |
| list_operations | The operations Guild would import for an OpenAPI or GraphQL surface. |
| get_apply_command | The exact npx command and agent prompt that build the draft. |
| get_porter_skill | This guide as SKILL.md. |
| search_catalog, get_catalog_entry | Porter's small reviewed catalog. |
| check_guild_drift, generate_guild_commands | Drift and guild CLI plans for catalog entries. |
How a run goes
1. Find
search_apis or /v1/search returns each surface's domain, surface slug, and kind.
2. Check
resolve_api says whether Guild can take it, and how it signs in. Unsupported surfaces come with a reason.
3. Build
The agent reads /v1/apply.ts, then runs npx -y <porter>/porter.tgz <domain> <surface> [--kind=…] with your logged-in guild CLI.
4. Hand back
The script stops after building version 1.0.0. Publish and credential connect are yours.
Every run ends with a porter-result: JSON line, so the agent knows what to ask you for:
| Status | Meaning |
|---|---|
| built | The draft exists. The agent reports the integration, what was imported, and the publish command. |
| needs-oauth-app | Exit 2. The provider has no self-registration: you create an OAuth app, the agent reruns with --client-id. |
| needs-connection | Exit 2. An OAuth MCP server needs your sign-in on the Guild dashboard before Guild can read its tools; then rerun. |
| failed | Exit 1. The agent reports the message, such as the failed build step. |
OAuth
Porter reads the authorize and token URLs, scopes, PKCE support, and token auth method from the spec or the provider's /.well-known metadata. If the provider registers clients itself, the script registers one for Guild's redirect URL on your machine. If not, it stops with the redirect URL, the scopes, and where to create the app; you create it, and the agent reruns with --client-id.
The client secret goes in PORTER_OAUTH_CLIENT_SECRET or a file passed with --client-secret-file. It never goes in chat or on the command line, and Porter never receives it. OAuth sign-in happens in the Guild dashboard, because the guild CLI cannot do it.
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 the guild commands without creating anything. |
| --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 set PORTER_OAUTH_CLIENT_SECRET. |
| --public-client | OAuth app with no secret. |
| --no-register | Skip automatic OAuth 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, --token-url | OAuth URLs from the provider's docs, when Porter cannot find them. |
What the agent may do
- Use the guild CLI already logged in on this machine. Logging in is your step.
- Create a private draft and build it. Never publish, and never connect a provider credential.
- Never ask for an API key or client secret in chat, and never put one on a command line.
- Leave the Guild token on this machine. Never print it, upload it, or pass it to Porter.
Endpoints
| URL | Returns |
|---|---|
| https://mcp.porter-guild.dev/mcp | MCP over streamable HTTP, served by the Porter API. |
| https://porter-guild.dev/v1/search?q= | Search integrations.sh. |
| https://porter-guild.dev/v1/resolve?domain=&surface=&kind= | Recipe or rejection reason. Add &auth=oauth to prefer OAuth. |
| https://porter-guild.dev/v1/openapi?domain=&surface=&kind= | The normalized OpenAPI document Guild imports. |
| https://porter-guild.dev/v1/prompt?domain=&surface=&kind= | A plain-text agent prompt. |
| https://porter-guild.dev/v1/apply.ts | The script porter.tgz runs. Read it before the first run. |
| https://porter-guild.dev/skill.md | The skill below. |