Pimpo
Documentation

Writing a connector#

A connector gives Pimpo new capabilities: tides.today, bank.balance, printer.print. Routines and explorations can only reach the world through capabilities, so a connector decides what becomes possible. For that reason Pimpo holds connectors to what they declare.

There are two kinds:

connector.json#

{
  "name": "tides",
  "description": "Tide tables for a port.",
  "command": "python3",
  "args": ["server.py"],
  "env": ["TIDES_KEY"],
  "capabilities": [
    {
      "name": "tides.today",
      "risk": "read",
      "signature": "tides.today({port})",
      "returns": "[{port, time, height_m, kind}]",
      "schema": {"type": "object", "required": ["port"], "properties": {"port": {"type": "string"}}}
    }
  ],
  "contract": [
    {"capability": "tides.today", "args": {"port": "Santos"}, "keys": ["port", "time", "height_m", "kind"]}
  ]
}

JSON connectors#

Replace command with http, and give each capability a request (and optionally a result):

{
  "name": "hnsearch",
  "description": "Hacker News search.",
  "env": ["EXAMPLE_KEY"],
  "http": {
    "base": "https://hn.algolia.com/api/v1",
    "headers": {"Authorization": "Bearer {{env.EXAMPLE_KEY}}"},
    "query": {}
  },
  "capabilities": [
    {
      "name": "hnsearch.stories",
      "risk": "read",
      "signature": "hnsearch.stories({query, min_points?, max?})",
      "returns": "[{title, url, points}]",
      "request": {"method": "GET", "path": "/search", "query": {"query": "{{query}}", "tags": "story", "numericFilters": "points>={{min_points}}", "hitsPerPage": "{{max}}"}},
      "result": {"path": "hits", "max": 50, "fields": {"title": "title", "url": "url", "points": "points"}}
    }
  ],
  "contract": [{"capability": "hnsearch.stories", "args": {"query": "rust"}, "keys": ["title", "points"]}]
}

Pimpo also enforces, for JSON connectors:

A POST that only reads (many APIs search that way) may be declared read with "safe": true in its request; it says so openly in the manifest.

From an OpenAPI description#

Most REST APIs publish an OpenAPI (Swagger) description, and Pimpo can write the connector.json from it:

pimpo connector openapi https://petstore3.swagger.io/api/v3/openapi.json
pimpo connector openapi --only get https://petstore3.swagger.io/api/v3/openapi.json petstore ./petstore
pimpo connector check ./petstore

What the import does:

What Pimpo enforces#

Checking and installing#

TIDES_KEY=... pimpo connector check ./tides

No part of Pimpo needs recompiling, and it does not need a restart either. Two ways to install:

cp -r ./tides ~/.pimpo/connectors/

The connector shows up in Connections with its capabilities, their risk, fields for the env vars it declares, and a Test button that runs the contract. Connectors travel with Export and import everything, like everything else.

Adding an existing MCP server#

Any MCP server works without writing a connector.json:

Pimpo connects, lists the tools and suggests a risk for each from the server's own hints (readOnlyHint, destructiveHint); a tool without hints counts as irreversible, so Pimpo asks before using it. The owner picks which tools to include and can change any risk before installing. Pimpo writes the connector.json itself (marked imported), keeps env values and headers in the vault, and from then on:

Registry servers are third-party code that Pimpo has not verified. Local ones run with a clean environment that holds only the variables you filled in.

Built-in connectors#

The catalog in Connections also has native connectors, written in Go with contract tests against fake servers in internal/connector/services:

ConnectorCapabilities
RSS and Atom🟢 rss.read (sites declared per routine)
Web search🟢 web.search (Brave Search API or a SearXNG instance)
GitHub🟢 github.repo, github.issues, github.issue, github.pulls, github.pr, github.checks, github.sponsors · 🟡 github.issue_create, github.issue_edit, github.pr_create, github.pr_review · 🔴 github.comment, github.merge, github.release
YouTube🟢 youtube.stats · 🔴 youtube.publish (uploads, always private, are Pimpo's own youtube.upload)
LinkedInposts through Pimpo's own linkedin.post 🔴, which adds the AI disclosure for company members
Stripe🟢 stripe.balance, stripe.charges (a restricted, read-only key)
Todoist🟢 todoist.tasks · 🟡 todoist.add, todoist.close
Notion🟢 notion.search · 🟡 notion.append
Obsidian🟢 obsidian.search · 🟡 obsidian.append (keeps the previous version)
Home Assistant🟢 ha.states · 🟡 ha.call · 🔴 ha.critical (locks, alarms, covers, valves; always asks)
Slack, Discord🔵 slack.send, discord.send (the owner's own channel, through a webhook)

The core connectors are Google Calendar and iCal, Gmail and IMAP, SMTP, HTTP JSON with declared hosts, Telegram and WhatsApp.

This page is built from the repository's documentation. Improve it on GitHub.