stargazer for agents
connect it to a chat client, or drive the /v1 api: documents in, a podcast episode out, one credit per episode.
Stargazer reads the documents you give it, writes a short script grounded in what they actually say, and voices it into a podcast episode on a private RSS feed. The dashboard drives that by hand. This API is the same pipeline addressed with a bearer key, built for agents and scripts working on a subscriber's behalf.
The same contract, written as a skill file you can hand straight to your agent, lives at /agents/skill.md.
Stargazer answers as an MCP connector at https://stargazer.vector.garden/mcp. Connect it once and episodes get made from inside a conversation: your agent hands over the report it was going to write anyway, and the finished episode turns up on your private feed. No file to save, no upload, no trip back to the dashboard.
In Claude Code that is two commands, and no key is involved:
claude mcp add --transport http stargazer https://stargazer.vector.garden/mcp
claude mcp login stargazer
A browser opens, you sign in with the email on your account, and you approve the connection once. That is the whole setup.
In claude.ai you add a custom connector pointing at https://stargazer.vector.garden/mcp instead. It takes a few minutes, most of that reading dialogs, and you do it once:
- Open Settings, then Connectors (it sits under Advanced), then "Add custom connector".
- Name it Stargazer and paste https://stargazer.vector.garden/mcp in as the url.
- Claude probes the server the moment the url lands and fills the rest in itself. You get "Detected" against the authentication choice and against the hosted client metadata one. Leave both exactly as detected, and skip the request headers section entirely: that lane is for api keys, not this one.
- Click Add. Claude opens a sign-in page, and the address you type there has to be the one on your Stargazer account.
- A sign-in link arrives by email. Look in spam first if it takes more than a minute, and open it in the same browser.
- The link lands on a consent screen headed "connect claude?". It says what Claude will be able to do. Approve it once.
- Back in Claude, open the tools menu in any chat and switch Stargazer on. The first tool call asks your permission, and approving an episode is approving spending one.
Claude Desktop has the same screen under a different name. Open Settings, then Extensions, then "Browse Extensions", which is where its connectors live. Click Add, name it Stargazer, paste https://stargazer.vector.garden/mcp into "Remote MCP server URL", and click Continue. It signs in and connects on its own from there.
Codex takes the same address through its plugin list. Open Plugins, then Add, then MCP server, and pick "Streamable HTTP" as the transport. Give it the name and the address and save. Stargazer then appears in the list of MCP plugins with an Authenticate button beside it: signing in is that click, after the server is saved rather than during.
Connecting the same app again later replaces the connection rather than adding a second one, so redoing any of that is safe.
Signing in with an email that has no subscription behind it still connects: the tools then say so and send you to /account, which is the only place that can fix it.
An agent with no browser to open, running headless or in CI, sends a workspace
key on the same Authorization header every other call here uses, and
skips the login step. The card below says where that key comes from.
claude mcp add --transport http stargazer https://stargazer.vector.garden/mcp --header "Authorization: Bearer sgk_your_key_here"
Four tools come with it:
- generate_episode: makes one out of material you already hold, and spends one credit.
- get_episode_status: where a given episode has got to.
- list_episodes: what this account has made, and the id a conversation lost.
- get_feed_url: the private feed address. It is a credential, exactly as it is over http.
Making an episode answers straight away with an id, and writing and voicing take a few minutes. Check every 20 to 30 seconds rather than in a tight loop, and stop whenever you like: the finished episode lands on the feed whether or not anyone is still watching.
Signing in works now: claude.ai custom connectors, Claude Desktop, Claude Code and Codex all connect by signing in with the email on the account, and any client that sends a Bearer header connects the way it always did. ChatGPT developer mode has not been tested against this endpoint yet, so treat it as untested rather than supported.
Keys belong to subscribers. The subscription is $25 a month for 25 episodes each cycle, and a pack of 10 more costs $10 when a cycle runs short. Sign in at /account, find the "connect your agent" card, and create a key. It is shown exactly once, so store it then.
A key is for a script, a CI job, or anything else with no browser to open. An agent working inside a chat takes the shorter road above instead, and no key changes hands.
The key spends those credits, one per accepted episode. It cannot buy credits, cannot start a subscription, and never touches a card. Money moves only when a person moves it in a browser.
An agent can ask for a quote before it holds an account or a key. Quoting is
free, needs neither, and generates nothing: the answer carries the price, the exact
job it covers, when it stops being true, and the call that spends it with the url
already composed. Redeeming with no key is not switched on for this deployment today, so that call
answers E_X402_DISABLED and says so. A workspace key redeems the same quote and spends a
credit, exactly as an ordinary submit does. The whole quote contract, refusal codes
and all, is written out in the skill file.
Ask what your key can do before you spend anything. The answer carries the workspace's caps, its voices, today's usage, and the credit balance.
curl https://stargazer.vector.garden/v1/workspace -H "Authorization: Bearer sgk_your_key_here"
Turn a PDF into text. Stateless: nothing is stored, and the text comes back for you to submit as an ordinary source.
curl -X POST https://stargazer.vector.garden/v1/extract -H "Authorization: Bearer sgk_your_key_here" -H "Content-Type: application/pdf" --data-binary @paper.pdf
Make an episode. One credit is spent when the submit is accepted, and the 202 carries the new balance. Sources can be https urls, or inline text objects when you already hold the material. An inline source can carry a label, and that is the name it is listed under in the finished episode's show notes.
curl -X POST https://stargazer.vector.garden/v1/episodes -H "Authorization: Bearer sgk_your_key_here" -H "Content-Type: application/json" -d '{"title": "What the handbook says", "sources": ["https://example.com/handbook.pdf"]}'
Only title and sources are required. Four optional fields shape the result, and the 202 echoes back the ones the run will actually use, so you can check a submit landed the way you meant it:
- shape: one of the shapes listed in GET /v1/workspace. "conversation" is two voices working through the material and is the default. "briefing" is one voice and essentials only. "critique" is two voices both skeptical of the document. "debate" is two voices holding opposite sides, and only earns its keep when the material genuinely has two.
- targetMinutes: how long the episode should run, up to the maxTargetMinutes cap. Asking for more than the cap is clamped rather than refused.
- focus: a sentence naming the question the episode should answer. The strongest single lever on what the script argues.
- tone: a phrase describing how it should sound.
Source order is not cosmetic. Citation markers are numbered in the order you supply the sources, so [S1] is your first source for the life of the episode, and the script tends to build its argument along the sequence you chose. Putting a claim before its rebuttal reads as a reversal; the reverse order reads as a hedge.
Voices come in two grades, premium and standard. A paid workspace gets premium by default, so most submits should send no voices field at all. Pass "voices": "standard" in the body for the plainer pair. The workspace answer's voices field names the grade a plain submit gets.
List what exists, poll one episode, and fetch its audio and transcript once the status says done. Most episodes finish in a few minutes, though a busy voice provider can stretch that to several. Poll every 20 to 30 seconds: status moves through queued and running to either done or error, and those two are the only states worth acting on.
curl https://stargazer.vector.garden/v1/episodes -H "Authorization: Bearer sgk_your_key_here"
curl https://stargazer.vector.garden/v1/episodes/EPISODE_ID -H "Authorization: Bearer sgk_your_key_here"
curl https://stargazer.vector.garden/v1/episodes/EPISODE_ID/audio -H "Authorization: Bearer sgk_your_key_here" -o episode.mp3
curl https://stargazer.vector.garden/v1/episodes/EPISODE_ID/transcript -H "Authorization: Bearer sgk_your_key_here"
- 401: the key is wrong, rotated, or revoked. Ask your human for the current one.
- 400: something in the body is off, and the error names the field. Nothing was spent, and no slot of the daily limit was used. A body that is not valid JSON at all answers "invalid JSON body" and can name no field, because nothing parsed.
- 400 on a short source: every source has to clear the minSourceChars floor in GET /v1/workspace. A one-paragraph note is usually under it.
- 402 E_NO_CREDITS: the account is out of episodes. Buying more happens on the account page, by a person.
- 402 E_PAST_DUE: the card behind the subscription is failing. Same page, same person.
- 403 E_NOT_ACTIVE: the subscription has ended.
- 403 E_FEED_RETIRED: the feed is switched off. Resubscribing brings it back.
- 403 E_VOICES_UNAVAILABLE: that voice grade is not on this workspace. Send no voices field, or the other grade.
- 413: a document is over the size cap. The caps are in GET /v1/workspace.
- 429: the daily episode limit. It resets when the UTC day does.
A refusal that arrives before the credit check costs nothing at all. One that arrives after it, which is any of the 402s, has already taken a slot of the daily limit even though no credit was spent, so a loop of hopeless retries burns the day. Never loop on a 402 or a 403: those answers do not change until a person acts.
Some promises hold everywhere on this rail. An identical resubmit dedupes to the episode that already exists and spends nothing. An episode that fails after spending a credit hands the credit back on its own. And the API never charges a card, whatever it is asked.
Two response shapes, and they differ. The submit answers flat, with episodeId and status at the top level. Reading one episode back wraps it: the row sits under an episode key, beside a workflow key describing the run. Write the two parsers separately rather than assuming one shape.
The row carries more than the documented fields, because it is the internal record. duration_ms and status are the two worth relying on. Anything else may change without notice.
The transcript comes back as plain text, not JSON, with each turn wrapped in speaker tags and citation markers sitting inline. Parse it by opening tag: the writer occasionally closes a turn with the other speaker's tag, and the pipeline tolerates that on purpose, so anything that insists on well-formed XML will break on an episode that is otherwise perfect.
GET /v1/workspace hands back the feed url for the account. Treat it as a credential. Its address is the only thing protecting the feed, so anyone who reads it can read every episode on it. Do not log it, do not paste it into a report, and do not send it anywhere your human did not ask you to send it.
- /openapi.json: every endpoint, body, status and error code, as OpenAPI 3.1. Its test suite walks it against the live router in both directions, so it cannot quietly describe a route that no longer exists.
- /llms.txt: one screen of orientation, for pasting into a coding agent.
- /agents/skill.md: this contract as a skill file.
- /.well-known/api-catalog: the RFC 9727 linkset naming all of the above.
There is an MCP server too, so the same calls arrive as tools your agent can
choose between rather than as http you have to write.
It answers at https://stargazer.vector.garden/mcp, either to a
signed-in person or to a workspace key on Authorization: Bearer, and
the setup for both is in connect it to your chat above.
Read its stargazer://service resource first: it states what the
service is, who publishes it, and the shapes an episode can take.